pax_global_header00006660000000000000000000000064151040011230014475gustar00rootroot0000000000000052 comment=423702f16d38b3ff95d1c7ec05def81ce7d3f3d6 x-0.4.9/000077500000000000000000000000001510400112300117565ustar00rootroot00000000000000x-0.4.9/.editorconfig000066400000000000000000000005431510400112300144350ustar00rootroot00000000000000; https://editorconfig.org/ root = true [*] insert_final_newline = true charset = utf-8 trim_trailing_whitespace = true indent_style = space indent_size = 2 [{Makefile,go.mod,go.sum,*.go,.gitmodules}] indent_style = tab indent_size = 4 [*.md] indent_size = 4 trim_trailing_whitespace = false eclint_indent_style = unset [Dockerfile] indent_size = 4 x-0.4.9/.github/000077500000000000000000000000001510400112300133165ustar00rootroot00000000000000x-0.4.9/.github/CODEOWNERS000066400000000000000000000001371510400112300147120ustar00rootroot00000000000000# The maintainers team is a code owner for the whole repository. * @go-crypt/maintainers x-0.4.9/.github/workflows/000077500000000000000000000000001510400112300153535ustar00rootroot00000000000000x-0.4.9/.github/workflows/go.yml000066400000000000000000000014641510400112300165100ustar00rootroot00000000000000name: Go on: pull_request: {} push: branches: - master jobs: build: name: Build runs-on: ubuntu-latest strategy: matrix: go: - '1.23' - '1.24' - '1.25' fail-fast: false steps: - name: Set up Go ${{ matrix.go }} uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} - name: Check out code into the Go module directory uses: actions/checkout@v3 - name: Get dependencies run: | go get -v -t -d ./... if [ -f Gopkg.toml ]; then curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh dep ensure fi #- name: Build # run: go build -v ./... - name: Test run: go test -v ./... x-0.4.9/.gitignore000066400000000000000000000010141510400112300137420ustar00rootroot00000000000000### Go ### # If you prefer the allow list template instead of the deny list, see community template: # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore # # Binaries for programs and plugins *.exe *.exe~ *.dll *.so *.dylib # Test binary, built with `go test -c` *.test # Output of the go coverage tool, specifically when used with LiteIDE *.out # Dependency directories (remove the comment below to include it) # vendor/ # Go workspace file go.work ### Go Patch ### /vendor/ /Godeps/x-0.4.9/.renovaterc000066400000000000000000000006571510400112300141370ustar00rootroot00000000000000{ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "constraints": { "go": "1.25" }, "extends": [ "config:recommended", ":semanticCommitTypeAll(build)", ":separatePatchReleases" ], "ignorePresets": [ ":combinePatchMinorReleases", ":prHourlyLimit2", ":semanticPrefixFixDepsChoreOthers" ], "enabledManagers": [ "gomod" ], "postUpdateOptions": [ "gomodTidy" ] } x-0.4.9/LICENSE000066400000000000000000000027071510400112300127710ustar00rootroot00000000000000Copyright (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. x-0.4.9/README.md000066400000000000000000000014051510400112300132350ustar00rootroot00000000000000[![Go Reference](https://pkg.go.dev/badge/github.com/go-crypt/x.svg)](https://pkg.go.dev/github.com/go-crypt/x) # github.com/go-crypt/x Low level library which copies several elements from [golang.org/x/crypto] and [github.com/openwall/yescrypt-go]. For a higher level library see [github.com/go-crypt/crypt]. ## Intent This library aims to implement feature parity with [golang.org/x/crypto] except for the following alterations: - Only crypt functions and functions to support these exist - Expose more methods - Adjust existing methods to have better uniformity [golang.org/x/crypto]: https://pkg.go.dev/golang.org/x/crypto [github.com/go-crypt/crypt]: https://github.com/go-crypt/crypt [github.com/openwall/yescrypt-go]: https://github.com/openwall/yescrypt-go x-0.4.9/argon2/000077500000000000000000000000001510400112300131465ustar00rootroot00000000000000x-0.4.9/argon2/README.md000066400000000000000000000001511510400112300144220ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/bda2f3f5cfce3f27039acccd823693f6d67c2a74/argon2 x-0.4.9/argon2/_asm/000077500000000000000000000000001510400112300140655ustar00rootroot00000000000000x-0.4.9/argon2/_asm/blamka_amd64.go000066400000000000000000000141141510400112300166370ustar00rootroot00000000000000// Copyright 2024 The Go Authors. 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 ( _ "github.com/go-crypt/x/argon2" . "github.com/mmcloughlin/avo/build" . "github.com/mmcloughlin/avo/operand" . "github.com/mmcloughlin/avo/reg" ) //go:generate go run . -out ../blamka_amd64.s -pkg argon2 func main() { Package("github.com/go-crypt/x/argon2") ConstraintExpr("amd64,gc,!purego") blamkaSSE4() mixBlocksSSE2() xorBlocksSSE2() Generate() } func blamkaSSE4() { Implement("blamkaSSE4") Attributes(NOSPLIT) AllocLocal(0) Load(Param("b"), RAX) c40 := c40_DATA() c48 := c48_DATA() MOVOU(c40, X10) MOVOU(c48, 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() { Implement("mixBlocksSSE2") Attributes(NOSPLIT) AllocLocal(0) Load(Param("out"), RDX) Load(Param("a"), RAX) Load(Param("b"), RBX) Load(Param("c"), RCX) MOVQ(U32(128), RDI) Label("loop") MOVOU(Mem{Base: AX}.Offset(0), X0) MOVOU(Mem{Base: BX}.Offset(0), X1) MOVOU(Mem{Base: CX}.Offset(0), X2) PXOR(X1, X0) PXOR(X2, X0) MOVOU(X0, Mem{Base: DX}.Offset(0)) ADDQ(Imm(16), RAX) ADDQ(Imm(16), RBX) ADDQ(Imm(16), RCX) ADDQ(Imm(16), RDX) SUBQ(Imm(2), RDI) JA(LabelRef("loop")) RET() } func xorBlocksSSE2() { Implement("xorBlocksSSE2") Attributes(NOSPLIT) AllocLocal(0) Load(Param("out"), RDX) Load(Param("a"), RAX) Load(Param("b"), RBX) Load(Param("c"), RCX) MOVQ(U32(128), RDI) Label("loop") MOVOU(Mem{Base: AX}.Offset(0), X0) MOVOU(Mem{Base: BX}.Offset(0), X1) MOVOU(Mem{Base: CX}.Offset(0), X2) MOVOU(Mem{Base: DX}.Offset(0), X3) PXOR(X1, X0) PXOR(X2, X0) PXOR(X3, X0) MOVOU(X0, Mem{Base: DX}.Offset(0)) ADDQ(Imm(16), RAX) ADDQ(Imm(16), RBX) ADDQ(Imm(16), RCX) ADDQ(Imm(16), RDX) SUBQ(Imm(2), RDI) JA(LabelRef("loop")) RET() } func SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { 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) } func SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { 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) } func HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7, t0, c40, c48 VecPhysical) { MOVO(v0, t0) PMULULQ(v2, t0) PADDQ(v2, v0) PADDQ(t0, v0) PADDQ(t0, v0) PXOR(v0, v6) PSHUFD(Imm(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(Imm(63), v2) PXOR(t0, v2) MOVO(v1, t0) PMULULQ(v3, t0) PADDQ(v3, v1) PADDQ(t0, v1) PADDQ(t0, v1) PXOR(v1, v7) PSHUFD(Imm(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(Imm(63), v3) PXOR(t0, v3) } func LOAD_MSG_0(block GPPhysical, off int) { var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} for i, r := range registers { MOVOU(Mem{Base: block}.Offset(8*(off+(i*2))), r) } } func STORE_MSG_0(block GPPhysical, off int) { var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} for i, r := range registers { MOVOU(r, Mem{Base: block}.Offset(8*(off+(i*2)))) } } func LOAD_MSG_1(block GPPhysical, off int) { var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} for i, r := range registers { MOVOU(Mem{Base: block}.Offset(8*off+i*16*8), r) } } func STORE_MSG_1(block GPPhysical, off int) { var registers = []VecPhysical{X0, X1, X2, X3, X4, X5, X6, X7} for i, r := range registers { MOVOU(r, Mem{Base: block}.Offset(8*off+i*16*8)) } } func BLAMKA_ROUND_0(block GPPhysical, off int, t0, t1, c40, c48 VecPhysical) { 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) } func BLAMKA_ROUND_1(block GPPhysical, off int, t0, t1, c40, c48 VecPhysical) { 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) } // ##------------------DATA SECTION-------------------## var c40_DATA_ptr, c48_DATA_ptr *Mem func c40_DATA() Mem { if c40_DATA_ptr != nil { return *c40_DATA_ptr } c40_DATA := GLOBL("·c40", NOPTR|RODATA) c40_DATA_ptr = &c40_DATA DATA(0x00, U64(0x0201000706050403)) DATA(0x08, U64(0x0a09080f0e0d0c0b)) return c40_DATA } func c48_DATA() Mem { if c48_DATA_ptr != nil { return *c48_DATA_ptr } c48_DATA := GLOBL("·c48", NOPTR|RODATA) c48_DATA_ptr = &c48_DATA DATA(0x00, U64(0x0100070605040302)) DATA(0x08, U64(0x09080f0e0d0c0b0a)) return c48_DATA } x-0.4.9/argon2/_asm/go.mod000066400000000000000000000004501510400112300151720ustar00rootroot00000000000000module argon2/_asm go 1.24.0 toolchain go1.25.4 require ( github.com/go-crypt/x v0.4.8 github.com/mmcloughlin/avo v0.6.0 ) require ( golang.org/x/mod v0.23.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/tools v0.30.0 // indirect ) x-0.4.9/argon2/_asm/go.sum000066400000000000000000000021351510400112300152210ustar00rootroot00000000000000github.com/go-crypt/x v0.4.8 h1:Cob6IxrSfWTc+MG8CBbNHBM4UqrBgEZDoK5t/SG4oZ4= github.com/go-crypt/x v0.4.8/go.mod h1:ozw9N4MYuLKhR5x2REs1e4T/nrEAkbuVkcsh/HbYksg= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= x-0.4.9/argon2/argon2.go000066400000000000000000000233741510400112300146760ustar00rootroot00000000000000// 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. // // # 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. // // # Argon2i // // Argon2i (implemented by IKey) 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. // // # Argon2d // // Argon2d (implemented by DKey) is the GPU cracking resistant version of Argon2. // It accesses the memory in a password dependent order which reduces the chances of // time-memory trade-off attacks but introduces side-channel attacks. // // [1] https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf // [2] https://www.rfc-editor.org/rfc/rfc9106.html package argon2 import ( "encoding/binary" "sync" "github.com/go-crypt/x/blake2b" ) // KeyFunc represents the functions which can derive keys. type KeyFunc func(password, salt []byte, time, memory, threads, keyLen uint32) []byte // 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, 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, 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, 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, threads) processBlocks(B, time, memory, threads, mode) return extractKey(B, memory, threads, keyLen) } // IKey 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 IKey(password, salt []byte, time, memory uint32, threads, keyLen uint32) []byte { return deriveKey(argon2i, password, salt, nil, nil, time, memory, threads, keyLen) } // DKey derives a key from the password, salt, and cost parameters using Argon2d // 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. func DKey(password, salt []byte, time, memory, threads, keyLen uint32) []byte { return deriveKey(argon2d, password, salt, nil, nil, time, memory, threads, keyLen) } 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)) } x-0.4.9/argon2/argon2_test.go000066400000000000000000000206231510400112300157270ustar00rootroot00000000000000// 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, 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, threads uint32 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", }, } x-0.4.9/argon2/blake2b.go000066400000000000000000000021211510400112300147730ustar00rootroot00000000000000// 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" "github.com/go-crypt/x/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]) } x-0.4.9/argon2/blamka_amd64.go000066400000000000000000000024731510400112300157250ustar00rootroot00000000000000// 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 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) } x-0.4.9/argon2/blamka_amd64.s000066400000000000000000001535671510400112300155750ustar00rootroot00000000000000// Code generated by command: go run blamka_amd64.go -out ../blamka_amd64.s -pkg argon2. DO NOT EDIT. //go:build amd64 && gc && !purego #include "textflag.h" // func blamkaSSE4(b *block) // Requires: SSE2, SSSE3 TEXT ·blamkaSSE4(SB), NOSPLIT, $0-8 MOVQ b+0(FP), AX MOVOU ·c40<>+0(SB), X10 MOVOU ·c48<>+0(SB), X11 MOVOU (AX), X0 MOVOU 16(AX), X1 MOVOU 32(AX), X2 MOVOU 48(AX), X3 MOVOU 64(AX), X4 MOVOU 80(AX), X5 MOVOU 96(AX), X6 MOVOU 112(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, (AX) MOVOU X1, 16(AX) MOVOU X2, 32(AX) MOVOU X3, 48(AX) MOVOU X4, 64(AX) MOVOU X5, 80(AX) MOVOU X6, 96(AX) MOVOU X7, 112(AX) MOVOU 128(AX), X0 MOVOU 144(AX), X1 MOVOU 160(AX), X2 MOVOU 176(AX), X3 MOVOU 192(AX), X4 MOVOU 208(AX), X5 MOVOU 224(AX), X6 MOVOU 240(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 128(AX) MOVOU X1, 144(AX) MOVOU X2, 160(AX) MOVOU X3, 176(AX) MOVOU X4, 192(AX) MOVOU X5, 208(AX) MOVOU X6, 224(AX) MOVOU X7, 240(AX) MOVOU 256(AX), X0 MOVOU 272(AX), X1 MOVOU 288(AX), X2 MOVOU 304(AX), X3 MOVOU 320(AX), X4 MOVOU 336(AX), X5 MOVOU 352(AX), X6 MOVOU 368(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 256(AX) MOVOU X1, 272(AX) MOVOU X2, 288(AX) MOVOU X3, 304(AX) MOVOU X4, 320(AX) MOVOU X5, 336(AX) MOVOU X6, 352(AX) MOVOU X7, 368(AX) MOVOU 384(AX), X0 MOVOU 400(AX), X1 MOVOU 416(AX), X2 MOVOU 432(AX), X3 MOVOU 448(AX), X4 MOVOU 464(AX), X5 MOVOU 480(AX), X6 MOVOU 496(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 384(AX) MOVOU X1, 400(AX) MOVOU X2, 416(AX) MOVOU X3, 432(AX) MOVOU X4, 448(AX) MOVOU X5, 464(AX) MOVOU X6, 480(AX) MOVOU X7, 496(AX) MOVOU 512(AX), X0 MOVOU 528(AX), X1 MOVOU 544(AX), X2 MOVOU 560(AX), X3 MOVOU 576(AX), X4 MOVOU 592(AX), X5 MOVOU 608(AX), X6 MOVOU 624(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 512(AX) MOVOU X1, 528(AX) MOVOU X2, 544(AX) MOVOU X3, 560(AX) MOVOU X4, 576(AX) MOVOU X5, 592(AX) MOVOU X6, 608(AX) MOVOU X7, 624(AX) MOVOU 640(AX), X0 MOVOU 656(AX), X1 MOVOU 672(AX), X2 MOVOU 688(AX), X3 MOVOU 704(AX), X4 MOVOU 720(AX), X5 MOVOU 736(AX), X6 MOVOU 752(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 640(AX) MOVOU X1, 656(AX) MOVOU X2, 672(AX) MOVOU X3, 688(AX) MOVOU X4, 704(AX) MOVOU X5, 720(AX) MOVOU X6, 736(AX) MOVOU X7, 752(AX) MOVOU 768(AX), X0 MOVOU 784(AX), X1 MOVOU 800(AX), X2 MOVOU 816(AX), X3 MOVOU 832(AX), X4 MOVOU 848(AX), X5 MOVOU 864(AX), X6 MOVOU 880(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 768(AX) MOVOU X1, 784(AX) MOVOU X2, 800(AX) MOVOU X3, 816(AX) MOVOU X4, 832(AX) MOVOU X5, 848(AX) MOVOU X6, 864(AX) MOVOU X7, 880(AX) MOVOU 896(AX), X0 MOVOU 912(AX), X1 MOVOU 928(AX), X2 MOVOU 944(AX), X3 MOVOU 960(AX), X4 MOVOU 976(AX), X5 MOVOU 992(AX), X6 MOVOU 1008(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 896(AX) MOVOU X1, 912(AX) MOVOU X2, 928(AX) MOVOU X3, 944(AX) MOVOU X4, 960(AX) MOVOU X5, 976(AX) MOVOU X6, 992(AX) MOVOU X7, 1008(AX) MOVOU (AX), X0 MOVOU 128(AX), X1 MOVOU 256(AX), X2 MOVOU 384(AX), X3 MOVOU 512(AX), X4 MOVOU 640(AX), X5 MOVOU 768(AX), X6 MOVOU 896(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, (AX) MOVOU X1, 128(AX) MOVOU X2, 256(AX) MOVOU X3, 384(AX) MOVOU X4, 512(AX) MOVOU X5, 640(AX) MOVOU X6, 768(AX) MOVOU X7, 896(AX) MOVOU 16(AX), X0 MOVOU 144(AX), X1 MOVOU 272(AX), X2 MOVOU 400(AX), X3 MOVOU 528(AX), X4 MOVOU 656(AX), X5 MOVOU 784(AX), X6 MOVOU 912(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 16(AX) MOVOU X1, 144(AX) MOVOU X2, 272(AX) MOVOU X3, 400(AX) MOVOU X4, 528(AX) MOVOU X5, 656(AX) MOVOU X6, 784(AX) MOVOU X7, 912(AX) MOVOU 32(AX), X0 MOVOU 160(AX), X1 MOVOU 288(AX), X2 MOVOU 416(AX), X3 MOVOU 544(AX), X4 MOVOU 672(AX), X5 MOVOU 800(AX), X6 MOVOU 928(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 32(AX) MOVOU X1, 160(AX) MOVOU X2, 288(AX) MOVOU X3, 416(AX) MOVOU X4, 544(AX) MOVOU X5, 672(AX) MOVOU X6, 800(AX) MOVOU X7, 928(AX) MOVOU 48(AX), X0 MOVOU 176(AX), X1 MOVOU 304(AX), X2 MOVOU 432(AX), X3 MOVOU 560(AX), X4 MOVOU 688(AX), X5 MOVOU 816(AX), X6 MOVOU 944(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 48(AX) MOVOU X1, 176(AX) MOVOU X2, 304(AX) MOVOU X3, 432(AX) MOVOU X4, 560(AX) MOVOU X5, 688(AX) MOVOU X6, 816(AX) MOVOU X7, 944(AX) MOVOU 64(AX), X0 MOVOU 192(AX), X1 MOVOU 320(AX), X2 MOVOU 448(AX), X3 MOVOU 576(AX), X4 MOVOU 704(AX), X5 MOVOU 832(AX), X6 MOVOU 960(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 64(AX) MOVOU X1, 192(AX) MOVOU X2, 320(AX) MOVOU X3, 448(AX) MOVOU X4, 576(AX) MOVOU X5, 704(AX) MOVOU X6, 832(AX) MOVOU X7, 960(AX) MOVOU 80(AX), X0 MOVOU 208(AX), X1 MOVOU 336(AX), X2 MOVOU 464(AX), X3 MOVOU 592(AX), X4 MOVOU 720(AX), X5 MOVOU 848(AX), X6 MOVOU 976(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 80(AX) MOVOU X1, 208(AX) MOVOU X2, 336(AX) MOVOU X3, 464(AX) MOVOU X4, 592(AX) MOVOU X5, 720(AX) MOVOU X6, 848(AX) MOVOU X7, 976(AX) MOVOU 96(AX), X0 MOVOU 224(AX), X1 MOVOU 352(AX), X2 MOVOU 480(AX), X3 MOVOU 608(AX), X4 MOVOU 736(AX), X5 MOVOU 864(AX), X6 MOVOU 992(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 96(AX) MOVOU X1, 224(AX) MOVOU X2, 352(AX) MOVOU X3, 480(AX) MOVOU X4, 608(AX) MOVOU X5, 736(AX) MOVOU X6, 864(AX) MOVOU X7, 992(AX) MOVOU 112(AX), X0 MOVOU 240(AX), X1 MOVOU 368(AX), X2 MOVOU 496(AX), X3 MOVOU 624(AX), X4 MOVOU 752(AX), X5 MOVOU 880(AX), X6 MOVOU 1008(AX), X7 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFD $0xb1, X6, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 PSHUFB X10, X2 MOVO X0, X8 PMULULQ X2, X8 PADDQ X2, X0 PADDQ X8, X0 PADDQ X8, X0 PXOR X0, X6 PSHUFB X11, X6 MOVO X4, X8 PMULULQ X6, X8 PADDQ X6, X4 PADDQ X8, X4 PADDQ X8, X4 PXOR X4, X2 MOVO X2, X8 PADDQ X2, X8 PSRLQ $0x3f, X2 PXOR X8, X2 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFD $0xb1, X7, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 PSHUFB X10, X3 MOVO X1, X8 PMULULQ X3, X8 PADDQ X3, X1 PADDQ X8, X1 PADDQ X8, X1 PXOR X1, X7 PSHUFB X11, X7 MOVO X5, X8 PMULULQ X7, X8 PADDQ X7, X5 PADDQ X8, X5 PADDQ X8, X5 PXOR X5, X3 MOVO X3, X8 PADDQ X3, X8 PSRLQ $0x3f, X3 PXOR X8, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVOU X0, 112(AX) MOVOU X1, 240(AX) MOVOU X2, 368(AX) MOVOU X3, 496(AX) MOVOU X4, 624(AX) MOVOU X5, 752(AX) MOVOU X6, 880(AX) MOVOU X7, 1008(AX) RET DATA ·c40<>+0(SB)/8, $0x0201000706050403 DATA ·c40<>+8(SB)/8, $0x0a09080f0e0d0c0b GLOBL ·c40<>(SB), RODATA|NOPTR, $16 DATA ·c48<>+0(SB)/8, $0x0100070605040302 DATA ·c48<>+8(SB)/8, $0x09080f0e0d0c0b0a GLOBL ·c48<>(SB), RODATA|NOPTR, $16 // func mixBlocksSSE2(out *block, a *block, b *block, c *block) // Requires: SSE2 TEXT ·mixBlocksSSE2(SB), NOSPLIT, $0-32 MOVQ out+0(FP), DX MOVQ a+8(FP), AX MOVQ b+16(FP), BX MOVQ c+24(FP), CX MOVQ $0x00000080, DI loop: MOVOU (AX), X0 MOVOU (BX), X1 MOVOU (CX), X2 PXOR X1, X0 PXOR X2, X0 MOVOU X0, (DX) ADDQ $0x10, AX ADDQ $0x10, BX ADDQ $0x10, CX ADDQ $0x10, DX SUBQ $0x02, DI JA loop RET // func xorBlocksSSE2(out *block, a *block, b *block, c *block) // Requires: SSE2 TEXT ·xorBlocksSSE2(SB), NOSPLIT, $0-32 MOVQ out+0(FP), DX MOVQ a+8(FP), AX MOVQ b+16(FP), BX MOVQ c+24(FP), CX MOVQ $0x00000080, DI loop: MOVOU (AX), X0 MOVOU (BX), X1 MOVOU (CX), X2 MOVOU (DX), X3 PXOR X1, X0 PXOR X2, X0 PXOR X3, X0 MOVOU X0, (DX) ADDQ $0x10, AX ADDQ $0x10, BX ADDQ $0x10, CX ADDQ $0x10, DX SUBQ $0x02, DI JA loop RET x-0.4.9/argon2/blamka_generic.go000066400000000000000000000104541510400112300164240ustar00rootroot00000000000000// 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 } x-0.4.9/argon2/blamka_ref.go000066400000000000000000000006051510400112300155610ustar00rootroot00000000000000// 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 package argon2 func processBlock(out, in1, in2 *block) { processBlockGeneric(out, in1, in2, false) } func processBlockXOR(out, in1, in2 *block) { processBlockGeneric(out, in1, in2, true) } x-0.4.9/argon2/const.go000066400000000000000000000003001510400112300146140ustar00rootroot00000000000000package argon2 const ( blockLength = 128 syncPoints = 4 ) // Version is the Argon2 version implemented by this package. const Version = 0x13 const ( argon2d = iota argon2i argon2id ) x-0.4.9/base64/000077500000000000000000000000001510400112300130425ustar00rootroot00000000000000x-0.4.9/base64/base64.go000066400000000000000000000020121510400112300144500ustar00rootroot00000000000000package base64 import ( "encoding/base64" ) var AdaptedEncoding = base64.NewEncoding(encodeAdapted) // BcryptEncoding is the Bcrypt Base64 Alternative encoding. var BcryptEncoding = base64.NewEncoding(bcryptB64Alphabet) // EncodeCrypt implements the linux crypt lib's B64 encoding. func EncodeCrypt(src []byte) (dst []byte) { if len(src) == 0 { return nil } dst = make([]byte, (len(src)*8+5)/6) idst, isrc := 0, 0 for isrc < len(src)/3*3 { v := uint(src[isrc+2])<<16 | uint(src[isrc+1])<<8 | uint(src[isrc]) dst[idst+0] = cryptB64Alphabet[v&0x3f] dst[idst+1] = cryptB64Alphabet[v>>6&0x3f] dst[idst+2] = cryptB64Alphabet[v>>12&0x3f] dst[idst+3] = cryptB64Alphabet[v>>18] idst += 4 isrc += 3 } remainder := len(src) - isrc if remainder == 0 { return dst } v := uint(src[isrc+0]) if remainder == 2 { v |= uint(src[isrc+1]) << 8 } dst[idst+0] = cryptB64Alphabet[v&0x3f] dst[idst+1] = cryptB64Alphabet[v>>6&0x3f] if remainder == 2 { dst[idst+2] = cryptB64Alphabet[v>>12] } return dst } x-0.4.9/base64/const.go000066400000000000000000000004421510400112300145170ustar00rootroot00000000000000package base64 const ( cryptB64Alphabet = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" bcryptB64Alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" encodeAdapted = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789./" ) x-0.4.9/bcrypt/000077500000000000000000000000001510400112300132615ustar00rootroot00000000000000x-0.4.9/bcrypt/README.md000066400000000000000000000001511510400112300145350ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/bc7d1d1eb54b3530da4f5ec31625c95d7df40231/bcrypt x-0.4.9/bcrypt/base64.go000066400000000000000000000015171510400112300147000ustar00rootroot00000000000000// 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 ( "github.com/go-crypt/x/base64" ) // Base64Encode is the base64 encoder for bcrypt. func Base64Encode(src []byte) []byte { n := base64.BcryptEncoding.EncodedLen(len(src)) dst := make([]byte, n) base64.BcryptEncoding.Encode(dst, src) for dst[n-1] == '=' { n-- } return dst[:n] } // Base64Decode is the base64 decoder for bcrypt. func Base64Decode(src []byte) ([]byte, error) { numOfEquals := 4 - (len(src) % 4) for i := 0; i < numOfEquals; i++ { src = append(src, '=') } dst := make([]byte, base64.BcryptEncoding.DecodedLen(len(src))) n, err := base64.BcryptEncoding.Decode(dst, src) if err != nil { return nil, err } return dst[:n], nil } x-0.4.9/bcrypt/bcrypt.go000066400000000000000000000170601510400112300151170ustar00rootroot00000000000000// 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 // The code is a port of Provos and Mazières's C implementation. import ( "crypto/rand" "crypto/subtle" "fmt" "io" "strconv" "github.com/go-crypt/x/blowfish" ) type hashed struct { hash []byte salt []byte cost int // allowed range is MinCost to MaxCost major byte minor byte } // 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. func GenerateFromPassword(password []byte, cost int) ([]byte, error) { p, err := newFromPassword(password, cost) if err != nil { return nil, err } return p.Hash(), nil } // GenerateFromPasswordSalt 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. func GenerateFromPasswordSalt(password, salt []byte, cost int) ([]byte, error) { p, err := newFromPasswordSalt(password, salt, cost) if err != nil { return nil, err } return p.Hash(), nil } // Key returns a new key from password/salt combination. Salt must be 16 bytes. For storage the salt needs to be encoded // with bcrypt.Base64Encode. func Key(password, salt []byte, cost int) ([]byte, error) { p, err := newFromPasswordSalt(password, salt, cost) if err != nil { return nil, err } return p.Key(), 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 := newFromHashPartial(hashedPassword) if err != nil { return 0, err } return p.cost, nil } // NewSalt generates a salt with an appropriate length. func NewSalt() (salt []byte, err error) { salt = make([]byte, maxSaltSize) _, err = io.ReadFull(rand.Reader, salt) return salt, err } func newFromPasswordSalt(password, salt []byte, cost int) (p *hashed, err error) { if cost < MinCost { cost = DefaultCost } p = new(hashed) p.major = majorVersion p.minor = minorVersion if err = checkSalt(salt); err != nil { return nil, err } p.salt = Base64Encode(salt) if err = checkCost(cost); err != nil { return nil, err } p.cost = cost hash, err := bcrypt(password, p.cost, p.salt) if err != nil { return nil, err } p.hash = hash return p, err } func newFromPassword(password []byte, cost int) (p *hashed, err error) { var salt []byte if salt, err = NewSalt(); err != nil { return nil, err } return newFromPasswordSalt(password, salt, cost) } func newFromHashPartial(hashedSecret []byte) (p *hashed, secret []byte, err error) { if len(hashedSecret) < minHashSize { return nil, nil, ErrHashTooShort } p = new(hashed) n, err := p.decodeVersion(hashedSecret) if err != nil { return nil, nil, err } hashedSecret = hashedSecret[n:] n, err = p.decodeCost(hashedSecret) if err != nil { return nil, nil, err } hashedSecret = hashedSecret[n:] return p, hashedSecret, nil } func newFromHash(hashedSecret []byte) (*hashed, error) { p, hashedSecret, err := newFromHashPartial(hashedSecret) if err != nil { return nil, err } if len(hashedSecret) != EncodedSaltSize+EncodedHashSize { return nil, ErrSecretInvalidLength } p.salt, p.hash = DecodeSecret(hashedSecret) return p, nil } // DecodeSecret decodes a valid bcrypt secret into a salt and key. This function will panic if the secret does not have // the len of EncodedSaltSize + EncodedHashSize. func DecodeSecret(secret []byte) (salt, key []byte) { if len(secret) != EncodedSaltSize+EncodedHashSize { panic("secret is malformed as it does not have the expected size") } salt, key = make([]byte, EncodedSaltSize, EncodedSaltSize), make([]byte, EncodedHashSize, EncodedHashSize) copy(salt, secret[:EncodedSaltSize]) copy(key, secret[EncodedSaltSize:]) return } 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) Key() []byte { return p.hash } 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:], 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 checkSalt(salt []byte) error { if len(salt) != maxSaltSize { return InvalidSaltSizeError{salt} } return nil } func checkCost(cost int) error { if cost < MinCost || cost > MaxCost { return InvalidCostError(cost) } return nil } x-0.4.9/bcrypt/bcrypt_test.go000066400000000000000000000172761510400112300161670ustar00rootroot00000000000000// 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" "github.com/stretchr/testify/assert" "testing" ) func TestDecodeSecret(t *testing.T) { testCases := []struct { name string have []byte expected []byte expectedSalt []byte shouldPanic bool }{ { "ShouldDecode", []byte("gKt7Q/V29tf48wMkEoYlNOk.XttO4IJdWKVDQPHLxkZMs9VEFwfv2"), []byte("k.XttO4IJdWKVDQPHLxkZMs9VEFwfv2"), []byte("gKt7Q/V29tf48wMkEoYlNO"), false, }, { "ShouldPanicOnInvalidSize", []byte("gKt7Q/V29tf48wMkEoYlN"), nil, nil, true, }, { "ShouldPanicWithEmptySecret", []byte(""), nil, nil, true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.shouldPanic { assert.Panics(t, func() { _, _ = DecodeSecret(tc.have) }) } else { assert.NotPanics(t, func() { salt, key := DecodeSecret(tc.have) assert.Equal(t, tc.expected, key) assert.Equal(t, tc.expectedSalt, salt) }) } }) } } 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) } } x-0.4.9/bcrypt/const.go000066400000000000000000000015261510400112300147420ustar00rootroot00000000000000package bcrypt 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 EncodedSaltSize = 22 EncodedHashSize = 31 ) const ( majorVersion = '2' minorVersion = 'a' maxSaltSize = 16 maxCryptedHashSize = 23 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, } x-0.4.9/bcrypt/errors.go000066400000000000000000000036431510400112300151320ustar00rootroot00000000000000package bcrypt import ( "errors" "fmt" ) var ( // ErrMismatchedHashAndPassword is the error returned from CompareHashAndPassword when a password and hash do // not match. ErrMismatchedHashAndPassword = errors.New("github.com/go-crypt/x/bcrypt: the provided password is not a match for the provided hashed password") // ErrHashTooShort is the error returned from CompareHashAndPassword when a hash is too short to // be a bcrypt hash. ErrHashTooShort = errors.New("github.com/go-crypt/x/bcrypt: hashed secret key is too short to be a bcrypt hashed secret key") // ErrSecretInvalidLength is the error returned when a hash secret is too short to be a bcrypt secret. ErrSecretInvalidLength = errors.New("github.com/go-crypt/x/bcrypt: secret has an invalid length for a bcrypt secret") ) // 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("github.com/go-crypt/x/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("github.com/go-crypt/x/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) } type InvalidCostError int func (ic InvalidCostError) Error() string { return fmt.Sprintf("github.com/go-crypt/x/bcrypt: cost %d is outside allowed inclusive range %d..%d", int(ic), MinCost, MaxCost) } type InvalidSaltSizeError struct { salt []byte } func (iss InvalidSaltSizeError) Error() string { return fmt.Sprintf("github.com/go-crypt/x/bcrypt: salt %x with byte length %d does not have the correct byte length %d", iss.salt, len(iss.salt), maxSaltSize) } x-0.4.9/blake2b/000077500000000000000000000000001510400112300132605ustar00rootroot00000000000000x-0.4.9/blake2b/README.md000066400000000000000000000001521510400112300145350ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/b8ffc16e10063067bac0e15c6d7f7995937503ce/blake2b x-0.4.9/blake2b/_asm/000077500000000000000000000000001510400112300141775ustar00rootroot00000000000000x-0.4.9/blake2b/_asm/standard/000077500000000000000000000000001510400112300157775ustar00rootroot00000000000000x-0.4.9/blake2b/_asm/standard/blake2b_amd64_asm.go000066400000000000000000000245521510400112300214730ustar00rootroot00000000000000// Copyright 2024 The Go Authors. 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 ( _ "github.com/go-crypt/x/blake2b" . "github.com/mmcloughlin/avo/build" . "github.com/mmcloughlin/avo/operand" . "github.com/mmcloughlin/avo/reg" ) //go:generate go run . -out ../../blake2b_amd64.s -pkg blake2b const ThatPeskyUnicodeDot = "\u00b7" var iv0_DATA_ptr, iv1_DATA_ptr, iv2_DATA_ptr, iv3_DATA_ptr, c40_DATA_ptr, c48_DATA_ptr *Mem func main() { Package("github.com/go-crypt/x/blake2b") ConstraintExpr("amd64,gc,!purego") hashBlocksSSE4() Generate() } func SHUFFLE(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { 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) } func SHUFFLE_INV(v2, v3, v4, v5, v6, v7, t1, t2 VecPhysical) { 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) } func HALF_ROUND(v0, v1, v2, v3, v4, v5, v6, v7 VecPhysical, m0, m1, m2, m3 Op, t0, c40, c48 VecPhysical) { PADDQ(m0, v0) PADDQ(m1, v1) PADDQ(v2, v0) PADDQ(v3, v1) PXOR(v0, v6) PXOR(v1, v7) PSHUFD(Imm(0xB1), v6, v6) PSHUFD(Imm(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(Imm(63), v2) PXOR(t0, v2) MOVOU(v3, t0) PADDQ(v3, t0) PSRLQ(Imm(63), v3) PXOR(t0, v3) } func LOAD_MSG(m0, m1, m2, m3 VecPhysical, src GPPhysical, i0, i1, i2, i3, i4, i5, i6, i7 int) { MOVQ(Mem{Base: src}.Offset(i0*8), m0) PINSRQ(Imm(1), Mem{Base: src}.Offset(i1*8), m0) MOVQ(Mem{Base: src}.Offset(i2*8), m1) PINSRQ(Imm(1), Mem{Base: src}.Offset(i3*8), m1) MOVQ(Mem{Base: src}.Offset(i4*8), m2) PINSRQ(Imm(1), Mem{Base: src}.Offset(i5*8), m2) MOVQ(Mem{Base: src}.Offset(i6*8), m3) PINSRQ(Imm(1), Mem{Base: src}.Offset(i7*8), m3) } func hashBlocksSSE4() { Implement("hashBlocksSSE4") Attributes(4) AllocLocal(288) // frame size = 272 + 16 byte alignment Load(Param("h"), RAX) Load(Param("c"), RBX) Load(Param("flag"), RCX) Load(Param("blocks").Base(), RSI) Load(Param("blocks").Len(), RDI) MOVQ(RSP, R10) ADDQ(Imm(15), R10) ANDQ(I32(-16), R10) iv3 := iv3_DATA() MOVOU(iv3, X0) MOVO(X0, Mem{Base: R10}.Offset(0)) XORQ(RCX, Mem{Base: R10}.Offset(0)) // 0(R10) = ·iv3 ^ (CX || 0) c40 := c40_DATA() c48 := c48_DATA() MOVOU(c40, X13) MOVOU(c48, X14) MOVOU(Mem{Base: AX}.Offset(0), X12) MOVOU(Mem{Base: AX}.Offset(16), X15) MOVQ(Mem{Base: BX}.Offset(0), R8) MOVQ(Mem{Base: BX}.Offset(8), R9) Label("loop") ADDQ(Imm(128), R8) CMPQ(R8, Imm(128)) JGE(LabelRef("noinc")) INCQ(R9) Label("noinc") MOVQ(R8, X8) PINSRQ(Imm(1), R9, X8) iv0 := iv0_DATA() iv1 := iv1_DATA() iv2 := iv2_DATA() MOVO(X12, X0) MOVO(X15, X1) MOVOU(Mem{Base: AX}.Offset(32), X2) MOVOU(Mem{Base: AX}.Offset(48), X3) MOVOU(iv0, X4) MOVOU(iv1, X5) MOVOU(iv2, X6) PXOR(X8, X6) MOVO(Mem{Base: R10}.Offset(0), X7) LOAD_MSG(X8, X9, X10, X11, SI, 0, 2, 4, 6, 1, 3, 5, 7) MOVO(X8, Mem{Base: R10}.Offset(16)) MOVO(X9, Mem{Base: R10}.Offset(32)) MOVO(X10, Mem{Base: R10}.Offset(48)) MOVO(X11, Mem{Base: R10}.Offset(64)) 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, Mem{Base: R10}.Offset(80)) MOVO(X9, Mem{Base: R10}.Offset(96)) MOVO(X10, Mem{Base: R10}.Offset(112)) MOVO(X11, Mem{Base: R10}.Offset(128)) 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, Mem{Base: R10}.Offset(144)) MOVO(X9, Mem{Base: R10}.Offset(160)) MOVO(X10, Mem{Base: R10}.Offset(176)) MOVO(X11, Mem{Base: R10}.Offset(192)) 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, Mem{Base: R10}.Offset(208)) MOVO(X9, Mem{Base: R10}.Offset(224)) MOVO(X10, Mem{Base: R10}.Offset(240)) MOVO(X11, Mem{Base: R10}.Offset(256)) 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, Mem{Base: R10}.Offset(16), Mem{Base: R10}.Offset(32), Mem{Base: R10}.Offset(48), Mem{Base: R10}.Offset(64), X11, X13, X14) SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(80), Mem{Base: R10}.Offset(96), Mem{Base: R10}.Offset(112), Mem{Base: R10}.Offset(128), X11, X13, X14) SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(144), Mem{Base: R10}.Offset(160), Mem{Base: R10}.Offset(176), Mem{Base: R10}.Offset(192), X11, X13, X14) SHUFFLE(X2, X3, X4, X5, X6, X7, X8, X9) HALF_ROUND(X0, X1, X2, X3, X4, X5, X6, X7, Mem{Base: R10}.Offset(208), Mem{Base: R10}.Offset(224), Mem{Base: R10}.Offset(240), Mem{Base: R10}.Offset(256), X11, X13, X14) SHUFFLE_INV(X2, X3, X4, X5, X6, X7, X8, X9) MOVOU(Mem{Base: AX}.Offset(32), X10) MOVOU(Mem{Base: AX}.Offset(48), 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, Mem{Base: AX}.Offset(32)) MOVOU(X11, Mem{Base: AX}.Offset(48)) LEAQ(Mem{Base: SI}.Offset(128), RSI) SUBQ(Imm(128), RDI) JNE(LabelRef("loop")) MOVOU(X12, Mem{Base: AX}.Offset(0)) MOVOU(X15, Mem{Base: AX}.Offset(16)) MOVQ(R8, Mem{Base: BX}.Offset(0)) MOVQ(R9, Mem{Base: BX}.Offset(8)) RET() } // #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~DATA SECTION~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~## func iv0_DATA() Mem { if iv0_DATA_ptr != nil { return *iv0_DATA_ptr } iv0 := GLOBL(ThatPeskyUnicodeDot+"iv0", NOPTR|RODATA) iv0_DATA_ptr = &iv0 DATA(0x00, U64(0x6a09e667f3bcc908)) DATA(0x08, U64(0xbb67ae8584caa73b)) return iv0 } func iv1_DATA() Mem { if iv1_DATA_ptr != nil { return *iv1_DATA_ptr } iv1 := GLOBL(ThatPeskyUnicodeDot+"iv1", NOPTR|RODATA) iv1_DATA_ptr = &iv1 DATA(0x00, U64(0x3c6ef372fe94f82b)) DATA(0x08, U64(0xa54ff53a5f1d36f1)) return iv1 } func iv2_DATA() Mem { if iv2_DATA_ptr != nil { return *iv2_DATA_ptr } iv2 := GLOBL(ThatPeskyUnicodeDot+"iv2", NOPTR|RODATA) iv2_DATA_ptr = &iv2 DATA(0x00, U64(0x510e527fade682d1)) DATA(0x08, U64(0x9b05688c2b3e6c1f)) return iv2 } func iv3_DATA() Mem { if iv3_DATA_ptr != nil { return *iv3_DATA_ptr } iv3 := GLOBL(ThatPeskyUnicodeDot+"iv3", NOPTR|RODATA) iv3_DATA_ptr = &iv3 DATA(0x00, U64(0x1f83d9abfb41bd6b)) DATA(0x08, U64(0x5be0cd19137e2179)) return iv3 } func c40_DATA() Mem { if c40_DATA_ptr != nil { return *c40_DATA_ptr } c40 := GLOBL(ThatPeskyUnicodeDot+"c40", NOPTR|RODATA) c40_DATA_ptr = &c40 DATA(0x00, U64(0x0201000706050403)) DATA(0x08, U64(0x0a09080f0e0d0c0b)) return c40 } func c48_DATA() Mem { if c48_DATA_ptr != nil { return *c48_DATA_ptr } c48 := GLOBL(ThatPeskyUnicodeDot+"c48", NOPTR|RODATA) c48_DATA_ptr = &c48 DATA(0x00, U64(0x0100070605040302)) DATA(0x08, U64(0x09080f0e0d0c0b0a)) return c48 } x-0.4.9/blake2b/_asm/standard/go.mod000066400000000000000000000004511510400112300171050ustar00rootroot00000000000000module blake2b/_asm go 1.24.0 toolchain go1.25.4 require ( github.com/go-crypt/x v0.4.8 github.com/mmcloughlin/avo v0.6.0 ) require ( golang.org/x/mod v0.23.0 // indirect golang.org/x/sync v0.11.0 // indirect golang.org/x/sys v0.36.0 // indirect golang.org/x/tools v0.30.0 // indirect ) x-0.4.9/blake2b/_asm/standard/go.sum000066400000000000000000000021351510400112300171330ustar00rootroot00000000000000github.com/go-crypt/x v0.4.8 h1:Cob6IxrSfWTc+MG8CBbNHBM4UqrBgEZDoK5t/SG4oZ4= github.com/go-crypt/x v0.4.8/go.mod h1:ozw9N4MYuLKhR5x2REs1e4T/nrEAkbuVkcsh/HbYksg= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/mmcloughlin/avo v0.6.0 h1:QH6FU8SKoTLaVs80GA8TJuLNkUYl4VokHKlPhVDg4YY= github.com/mmcloughlin/avo v0.6.0/go.mod h1:8CoAGaCSYXtCPR+8y18Y9aB/kxb8JSS6FRI7mSkvD+8= golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= x-0.4.9/blake2b/blake2b.go000066400000000000000000000161441510400112300151170ustar00rootroot00000000000000// 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" ) 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 } x-0.4.9/blake2b/blake2bAVX2_amd64.go000066400000000000000000000016111510400112300165440ustar00rootroot00000000000000// 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 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) } } x-0.4.9/blake2b/blake2bAVX2_amd64.s000066400000000000000000000572551510400112300164200ustar00rootroot00000000000000// 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 #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 x-0.4.9/blake2b/blake2b_amd64.s000066400000000000000000000725641510400112300157570ustar00rootroot00000000000000// Code generated by command: go run blake2b_amd64_asm.go -out ../../blake2b_amd64.s -pkg blake2b. DO NOT EDIT. //go:build amd64 && gc && !purego #include "textflag.h" // func hashBlocksSSE4(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) // Requires: SSE2, SSE4.1, SSSE3 TEXT ·hashBlocksSSE4(SB), NOSPLIT, $288-48 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 $0x0f, R10 ANDQ $-16, R10 MOVOU ·iv3<>+0(SB), X0 MOVO X0, (R10) XORQ CX, (R10) MOVOU ·c40<>+0(SB), X13 MOVOU ·c48<>+0(SB), X14 MOVOU (AX), X12 MOVOU 16(AX), X15 MOVQ (BX), R8 MOVQ 8(BX), R9 loop: ADDQ $0x80, R8 CMPQ R8, $0x80 JGE noinc INCQ R9 noinc: MOVQ R8, X8 PINSRQ $0x01, R9, X8 MOVO X12, X0 MOVO X15, X1 MOVOU 32(AX), X2 MOVOU 48(AX), X3 MOVOU ·iv0<>+0(SB), X4 MOVOU ·iv1<>+0(SB), X5 MOVOU ·iv2<>+0(SB), X6 PXOR X8, X6 MOVO (R10), X7 MOVQ (SI), X8 PINSRQ $0x01, 16(SI), X8 MOVQ 32(SI), X9 PINSRQ $0x01, 48(SI), X9 MOVQ 8(SI), X10 PINSRQ $0x01, 24(SI), X10 MOVQ 40(SI), X11 PINSRQ $0x01, 56(SI), X11 MOVO X8, 16(R10) MOVO X9, 32(R10) MOVO X10, 48(R10) MOVO X11, 64(R10) PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 64(SI), X8 PINSRQ $0x01, 80(SI), X8 MOVQ 96(SI), X9 PINSRQ $0x01, 112(SI), X9 MOVQ 72(SI), X10 PINSRQ $0x01, 88(SI), X10 MOVQ 104(SI), X11 PINSRQ $0x01, 120(SI), X11 MOVO X8, 80(R10) MOVO X9, 96(R10) MOVO X10, 112(R10) MOVO X11, 128(R10) PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 112(SI), X8 PINSRQ $0x01, 32(SI), X8 MOVQ 72(SI), X9 PINSRQ $0x01, 104(SI), X9 MOVQ 80(SI), X10 PINSRQ $0x01, 64(SI), X10 MOVQ 120(SI), X11 PINSRQ $0x01, 48(SI), X11 MOVO X8, 144(R10) MOVO X9, 160(R10) MOVO X10, 176(R10) MOVO X11, 192(R10) PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 8(SI), X8 PINSRQ $0x01, (SI), X8 MOVQ 88(SI), X9 PINSRQ $0x01, 40(SI), X9 MOVQ 96(SI), X10 PINSRQ $0x01, 16(SI), X10 MOVQ 56(SI), X11 PINSRQ $0x01, 24(SI), X11 MOVO X8, 208(R10) MOVO X9, 224(R10) MOVO X10, 240(R10) MOVO X11, 256(R10) PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 88(SI), X8 PINSRQ $0x01, 96(SI), X8 MOVQ 40(SI), X9 PINSRQ $0x01, 120(SI), X9 MOVQ 64(SI), X10 PINSRQ $0x01, (SI), X10 MOVQ 16(SI), X11 PINSRQ $0x01, 104(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 80(SI), X8 PINSRQ $0x01, 24(SI), X8 MOVQ 56(SI), X9 PINSRQ $0x01, 72(SI), X9 MOVQ 112(SI), X10 PINSRQ $0x01, 48(SI), X10 MOVQ 8(SI), X11 PINSRQ $0x01, 32(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 56(SI), X8 PINSRQ $0x01, 24(SI), X8 MOVQ 104(SI), X9 PINSRQ $0x01, 88(SI), X9 MOVQ 72(SI), X10 PINSRQ $0x01, 8(SI), X10 MOVQ 96(SI), X11 PINSRQ $0x01, 112(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 16(SI), X8 PINSRQ $0x01, 40(SI), X8 MOVQ 32(SI), X9 PINSRQ $0x01, 120(SI), X9 MOVQ 48(SI), X10 PINSRQ $0x01, 80(SI), X10 MOVQ (SI), X11 PINSRQ $0x01, 64(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 72(SI), X8 PINSRQ $0x01, 40(SI), X8 MOVQ 16(SI), X9 PINSRQ $0x01, 80(SI), X9 MOVQ (SI), X10 PINSRQ $0x01, 56(SI), X10 MOVQ 32(SI), X11 PINSRQ $0x01, 120(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 112(SI), X8 PINSRQ $0x01, 88(SI), X8 MOVQ 48(SI), X9 PINSRQ $0x01, 24(SI), X9 MOVQ 8(SI), X10 PINSRQ $0x01, 96(SI), X10 MOVQ 64(SI), X11 PINSRQ $0x01, 104(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 16(SI), X8 PINSRQ $0x01, 48(SI), X8 MOVQ (SI), X9 PINSRQ $0x01, 64(SI), X9 MOVQ 96(SI), X10 PINSRQ $0x01, 80(SI), X10 MOVQ 88(SI), X11 PINSRQ $0x01, 24(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 32(SI), X8 PINSRQ $0x01, 56(SI), X8 MOVQ 120(SI), X9 PINSRQ $0x01, 8(SI), X9 MOVQ 104(SI), X10 PINSRQ $0x01, 40(SI), X10 MOVQ 112(SI), X11 PINSRQ $0x01, 72(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 96(SI), X8 PINSRQ $0x01, 8(SI), X8 MOVQ 112(SI), X9 PINSRQ $0x01, 32(SI), X9 MOVQ 40(SI), X10 PINSRQ $0x01, 120(SI), X10 MOVQ 104(SI), X11 PINSRQ $0x01, 80(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ (SI), X8 PINSRQ $0x01, 48(SI), X8 MOVQ 72(SI), X9 PINSRQ $0x01, 64(SI), X9 MOVQ 56(SI), X10 PINSRQ $0x01, 24(SI), X10 MOVQ 16(SI), X11 PINSRQ $0x01, 88(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 104(SI), X8 PINSRQ $0x01, 56(SI), X8 MOVQ 96(SI), X9 PINSRQ $0x01, 24(SI), X9 MOVQ 88(SI), X10 PINSRQ $0x01, 112(SI), X10 MOVQ 8(SI), X11 PINSRQ $0x01, 72(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 40(SI), X8 PINSRQ $0x01, 120(SI), X8 MOVQ 64(SI), X9 PINSRQ $0x01, 16(SI), X9 MOVQ (SI), X10 PINSRQ $0x01, 32(SI), X10 MOVQ 48(SI), X11 PINSRQ $0x01, 80(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 48(SI), X8 PINSRQ $0x01, 112(SI), X8 MOVQ 88(SI), X9 PINSRQ $0x01, (SI), X9 MOVQ 120(SI), X10 PINSRQ $0x01, 72(SI), X10 MOVQ 24(SI), X11 PINSRQ $0x01, 64(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 96(SI), X8 PINSRQ $0x01, 104(SI), X8 MOVQ 8(SI), X9 PINSRQ $0x01, 80(SI), X9 MOVQ 16(SI), X10 PINSRQ $0x01, 56(SI), X10 MOVQ 32(SI), X11 PINSRQ $0x01, 40(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 MOVQ 80(SI), X8 PINSRQ $0x01, 64(SI), X8 MOVQ 56(SI), X9 PINSRQ $0x01, 8(SI), X9 MOVQ 16(SI), X10 PINSRQ $0x01, 32(SI), X10 MOVQ 48(SI), X11 PINSRQ $0x01, 40(SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 MOVQ 120(SI), X8 PINSRQ $0x01, 72(SI), X8 MOVQ 24(SI), X9 PINSRQ $0x01, 104(SI), X9 MOVQ 88(SI), X10 PINSRQ $0x01, 112(SI), X10 MOVQ 96(SI), X11 PINSRQ $0x01, (SI), X11 PADDQ X8, X0 PADDQ X9, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ X10, X0 PADDQ X11, X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 PADDQ 16(R10), X0 PADDQ 32(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ 48(R10), X0 PADDQ 64(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 PADDQ 80(R10), X0 PADDQ 96(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ 112(R10), X0 PADDQ 128(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 PADDQ 144(R10), X0 PADDQ 160(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ 176(R10), X0 PADDQ 192(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X6, X8 PUNPCKLQDQ X6, X9 PUNPCKHQDQ X7, X6 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X7, X9 MOVO X8, X7 MOVO X2, X8 PUNPCKHQDQ X9, X7 PUNPCKLQDQ X3, X9 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X3 PADDQ 208(R10), X0 PADDQ 224(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFD $0xb1, X6, X6 PSHUFD $0xb1, X7, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 PSHUFB X13, X2 PSHUFB X13, X3 PADDQ 240(R10), X0 PADDQ 256(R10), X1 PADDQ X2, X0 PADDQ X3, X1 PXOR X0, X6 PXOR X1, X7 PSHUFB X14, X6 PSHUFB X14, X7 PADDQ X6, X4 PADDQ X7, X5 PXOR X4, X2 PXOR X5, X3 MOVOU X2, X11 PADDQ X2, X11 PSRLQ $0x3f, X2 PXOR X11, X2 MOVOU X3, X11 PADDQ X3, X11 PSRLQ $0x3f, X3 PXOR X11, X3 MOVO X4, X8 MOVO X5, X4 MOVO X8, X5 MOVO X2, X8 PUNPCKLQDQ X2, X9 PUNPCKHQDQ X3, X2 PUNPCKHQDQ X9, X2 PUNPCKLQDQ X3, X9 MOVO X8, X3 MOVO X6, X8 PUNPCKHQDQ X9, X3 PUNPCKLQDQ X7, X9 PUNPCKHQDQ X9, X6 PUNPCKLQDQ X8, X9 PUNPCKHQDQ X9, X7 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 $0x80, DI JNE loop MOVOU X12, (AX) MOVOU X15, 16(AX) MOVQ R8, (BX) MOVQ R9, 8(BX) RET DATA ·iv3<>+0(SB)/8, $0x1f83d9abfb41bd6b DATA ·iv3<>+8(SB)/8, $0x5be0cd19137e2179 GLOBL ·iv3<>(SB), RODATA|NOPTR, $16 DATA ·c40<>+0(SB)/8, $0x0201000706050403 DATA ·c40<>+8(SB)/8, $0x0a09080f0e0d0c0b GLOBL ·c40<>(SB), RODATA|NOPTR, $16 DATA ·c48<>+0(SB)/8, $0x0100070605040302 DATA ·c48<>+8(SB)/8, $0x09080f0e0d0c0b0a GLOBL ·c48<>(SB), RODATA|NOPTR, $16 DATA ·iv0<>+0(SB)/8, $0x6a09e667f3bcc908 DATA ·iv0<>+8(SB)/8, $0xbb67ae8584caa73b GLOBL ·iv0<>(SB), RODATA|NOPTR, $16 DATA ·iv1<>+0(SB)/8, $0x3c6ef372fe94f82b DATA ·iv1<>+8(SB)/8, $0xa54ff53a5f1d36f1 GLOBL ·iv1<>(SB), RODATA|NOPTR, $16 DATA ·iv2<>+0(SB)/8, $0x510e527fade682d1 DATA ·iv2<>+8(SB)/8, $0x9b05688c2b3e6c1f GLOBL ·iv2<>(SB), RODATA|NOPTR, $16 x-0.4.9/blake2b/blake2b_generic.go000066400000000000000000000062251510400112300166120ustar00rootroot00000000000000// 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" ) 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 } x-0.4.9/blake2b/blake2b_ref.go000066400000000000000000000005101510400112300157410ustar00rootroot00000000000000// 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 package blake2b func hashBlocks(h *[8]uint64, c *[2]uint64, flag uint64, blocks []byte) { hashBlocksGeneric(h, c, flag, blocks) } x-0.4.9/blake2b/blake2b_test.go000066400000000000000000003253021510400112300161550ustar00rootroot00000000000000// 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", } x-0.4.9/blake2b/blake2x.go000066400000000000000000000073771510400112300151550ustar00rootroot00000000000000// 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. // // New callers should prefer the standard library [hash.XOF]. 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() } // 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. // // The result can be safely interface-upgraded to [hash.XOF]. 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) BlockSize() int { return x.d.BlockSize() } 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:]) } } x-0.4.9/blake2b/const.go000066400000000000000000000032141510400112300147350ustar00rootroot00000000000000package blake2b const ( // BlockSize of BLAKE2b in bytes. BlockSize = 128 // Size is the hash size of BLAKE2b-512 in bytes. Size = 64 // Size384 is the hash size of BLAKE2b-384 in bytes. Size384 = 48 // Size256 is the hash size of BLAKE2b-256 in bytes. Size256 = 32 ) const ( // OutputLengthUnknown can be used as the size argument to NewXOF to indicate // the length of the output is not known in advance. OutputLengthUnknown = 0 // magicUnknownOutputLength is a magic value for the output size that indicates // an unknown number of output bytes. magicUnknownOutputLength = (1 << 32) - 1 // maxOutputLength is the absolute maximum number of bytes to produce when the // number of output bytes is unknown. maxOutputLength = (1 << 32) * 64 ) // 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 } x-0.4.9/blake2b/go125.go000066400000000000000000000003601510400112300144430ustar00rootroot00000000000000// Copyright 2025 The Go 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.25 package blake2b import "hash" var _ hash.XOF = (*xof)(nil) x-0.4.9/blake2b/register.go000066400000000000000000000011221510400112300154270ustar00rootroot00000000000000// 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 ( "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) } x-0.4.9/blowfish/000077500000000000000000000000001510400112300135735ustar00rootroot00000000000000x-0.4.9/blowfish/README.md000066400000000000000000000001531510400112300150510ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/a57398324d7b9ce8afc47fed8168be52977536f1/blowfish x-0.4.9/blowfish/block.go000066400000000000000000000140211510400112300152120ustar00rootroot00000000000000// 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 } x-0.4.9/blowfish/blowfish_test.go000066400000000000000000000237261510400112300170100ustar00rootroot00000000000000// 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) } } x-0.4.9/blowfish/cipher.go000066400000000000000000000065031510400112300154000ustar00rootroot00000000000000// 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 package blowfish // The code is a port of Bruce Schneier's C implementation. // See https://www.schneier.com/blowfish.html. import "strconv" // 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:]) } x-0.4.9/blowfish/const.go000066400000000000000000000316231510400112300152550ustar00rootroot00000000000000// 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 // BlockSize is the Blowfish block size in bytes. const BlockSize = 8 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, } x-0.4.9/crypt/000077500000000000000000000000001510400112300131175ustar00rootroot00000000000000x-0.4.9/crypt/const.go000066400000000000000000000202241510400112300145740ustar00rootroot00000000000000package crypt var permuteTableMD5Crypt = [16]byte{ 12, 6, 0, 13, 7, 1, 14, 8, 2, 15, 9, 3, 5, 10, 4, 11, } var permuteTableSHA1Crypt = [21]byte{ 2, 1, 0, 5, 4, 3, 8, 7, 6, 11, 10, 9, 14, 13, 12, 17, 16, 15, 0, 19, 18, } var permuteTableSHACryptSHA256 = [32]byte{ 20, 10, 0, 11, 1, 21, 2, 22, 12, 23, 13, 3, 14, 4, 24, 5, 25, 15, 26, 16, 6, 17, 7, 27, 8, 28, 18, 29, 19, 9, 30, 31, } var permuteTableSHACryptSHA512 = [64]byte{ 42, 21, 0, 1, 43, 22, 23, 2, 44, 45, 24, 3, 4, 46, 25, 26, 5, 47, 48, 27, 6, 7, 49, 28, 29, 8, 50, 51, 30, 9, 10, 52, 31, 32, 11, 53, 54, 33, 12, 13, 55, 34, 35, 14, 56, 57, 36, 15, 16, 58, 37, 38, 17, 59, 60, 39, 18, 19, 61, 40, 41, 20, 62, 63, } // The following is the 1517 bytes of Hamlet III.ii which is public domain. This is used by Sun's MD5 Crypt function. var magicTableMD5CryptSunHamlet = [1517]byte{ 84, 111, 32, 98, 101, 44, 32, 111, 114, 32, 110, 111, 116, 32, 116, 111, 32, 98, 101, 44, 45, 45, 116, 104, 97, 116, 32, 105, 115, 32, 116, 104, 101, 32, 113, 117, 101, 115, 116, 105, 111, 110, 58, 45, 45, 10, 87, 104, 101, 116, 104, 101, 114, 32, 39, 116, 105, 115, 32, 110, 111, 98, 108, 101, 114, 32, 105, 110, 32, 116, 104, 101, 32, 109, 105, 110, 100, 32, 116, 111, 32, 115, 117, 102, 102, 101, 114, 10, 84, 104, 101, 32, 115, 108, 105, 110, 103, 115, 32, 97, 110, 100, 32, 97, 114, 114, 111, 119, 115, 32, 111, 102, 32, 111, 117, 116, 114, 97, 103, 101, 111, 117, 115, 32, 102, 111, 114, 116, 117, 110, 101, 10, 79, 114, 32, 116, 111, 32, 116, 97, 107, 101, 32, 97, 114, 109, 115, 32, 97, 103, 97, 105, 110, 115, 116, 32, 97, 32, 115, 101, 97, 32, 111, 102, 32, 116, 114, 111, 117, 98, 108, 101, 115, 44, 10, 65, 110, 100, 32, 98, 121, 32, 111, 112, 112, 111, 115, 105, 110, 103, 32, 101, 110, 100, 32, 116, 104, 101, 109, 63, 45, 45, 84, 111, 32, 100, 105, 101, 44, 45, 45, 116, 111, 32, 115, 108, 101, 101, 112, 44, 45, 45, 10, 78, 111, 32, 109, 111, 114, 101, 59, 32, 97, 110, 100, 32, 98, 121, 32, 97, 32, 115, 108, 101, 101, 112, 32, 116, 111, 32, 115, 97, 121, 32, 119, 101, 32, 101, 110, 100, 10, 84, 104, 101, 32, 104, 101, 97, 114, 116, 97, 99, 104, 101, 44, 32, 97, 110, 100, 32, 116, 104, 101, 32, 116, 104, 111, 117, 115, 97, 110, 100, 32, 110, 97, 116, 117, 114, 97, 108, 32, 115, 104, 111, 99, 107, 115, 10, 84, 104, 97, 116, 32, 102, 108, 101, 115, 104, 32, 105, 115, 32, 104, 101, 105, 114, 32, 116, 111, 44, 45, 45, 39, 116, 105, 115, 32, 97, 32, 99, 111, 110, 115, 117, 109, 109, 97, 116, 105, 111, 110, 10, 68, 101, 118, 111, 117, 116, 108, 121, 32, 116, 111, 32, 98, 101, 32, 119, 105, 115, 104, 39, 100, 46, 32, 84, 111, 32, 100, 105, 101, 44, 45, 45, 116, 111, 32, 115, 108, 101, 101, 112, 59, 45, 45, 10, 84, 111, 32, 115, 108, 101, 101, 112, 33, 32, 112, 101, 114, 99, 104, 97, 110, 99, 101, 32, 116, 111, 32, 100, 114, 101, 97, 109, 58, 45, 45, 97, 121, 44, 32, 116, 104, 101, 114, 101, 39, 115, 32, 116, 104, 101, 32, 114, 117, 98, 59, 10, 70, 111, 114, 32, 105, 110, 32, 116, 104, 97, 116, 32, 115, 108, 101, 101, 112, 32, 111, 102, 32, 100, 101, 97, 116, 104, 32, 119, 104, 97, 116, 32, 100, 114, 101, 97, 109, 115, 32, 109, 97, 121, 32, 99, 111, 109, 101, 44, 10, 87, 104, 101, 110, 32, 119, 101, 32, 104, 97, 118, 101, 32, 115, 104, 117, 102, 102, 108, 101, 100, 32, 111, 102, 102, 32, 116, 104, 105, 115, 32, 109, 111, 114, 116, 97, 108, 32, 99, 111, 105, 108, 44, 10, 77, 117, 115, 116, 32, 103, 105, 118, 101, 32, 117, 115, 32, 112, 97, 117, 115, 101, 58, 32, 116, 104, 101, 114, 101, 39, 115, 32, 116, 104, 101, 32, 114, 101, 115, 112, 101, 99, 116, 10, 84, 104, 97, 116, 32, 109, 97, 107, 101, 115, 32, 99, 97, 108, 97, 109, 105, 116, 121, 32, 111, 102, 32, 115, 111, 32, 108, 111, 110, 103, 32, 108, 105, 102, 101, 59, 10, 70, 111, 114, 32, 119, 104, 111, 32, 119, 111, 117, 108, 100, 32, 98, 101, 97, 114, 32, 116, 104, 101, 32, 119, 104, 105, 112, 115, 32, 97, 110, 100, 32, 115, 99, 111, 114, 110, 115, 32, 111, 102, 32, 116, 105, 109, 101, 44, 10, 84, 104, 101, 32, 111, 112, 112, 114, 101, 115, 115, 111, 114, 39, 115, 32, 119, 114, 111, 110, 103, 44, 32, 116, 104, 101, 32, 112, 114, 111, 117, 100, 32, 109, 97, 110, 39, 115, 32, 99, 111, 110, 116, 117, 109, 101, 108, 121, 44, 10, 84, 104, 101, 32, 112, 97, 110, 103, 115, 32, 111, 102, 32, 100, 101, 115, 112, 105, 115, 39, 100, 32, 108, 111, 118, 101, 44, 32, 116, 104, 101, 32, 108, 97, 119, 39, 115, 32, 100, 101, 108, 97, 121, 44, 10, 84, 104, 101, 32, 105, 110, 115, 111, 108, 101, 110, 99, 101, 32, 111, 102, 32, 111, 102, 102, 105, 99, 101, 44, 32, 97, 110, 100, 32, 116, 104, 101, 32, 115, 112, 117, 114, 110, 115, 10, 84, 104, 97, 116, 32, 112, 97, 116, 105, 101, 110, 116, 32, 109, 101, 114, 105, 116, 32, 111, 102, 32, 116, 104, 101, 32, 117, 110, 119, 111, 114, 116, 104, 121, 32, 116, 97, 107, 101, 115, 44, 10, 87, 104, 101, 110, 32, 104, 101, 32, 104, 105, 109, 115, 101, 108, 102, 32, 109, 105, 103, 104, 116, 32, 104, 105, 115, 32, 113, 117, 105, 101, 116, 117, 115, 32, 109, 97, 107, 101, 10, 87, 105, 116, 104, 32, 97, 32, 98, 97, 114, 101, 32, 98, 111, 100, 107, 105, 110, 63, 32, 119, 104, 111, 32, 119, 111, 117, 108, 100, 32, 116, 104, 101, 115, 101, 32, 102, 97, 114, 100, 101, 108, 115, 32, 98, 101, 97, 114, 44, 10, 84, 111, 32, 103, 114, 117, 110, 116, 32, 97, 110, 100, 32, 115, 119, 101, 97, 116, 32, 117, 110, 100, 101, 114, 32, 97, 32, 119, 101, 97, 114, 121, 32, 108, 105, 102, 101, 44, 10, 66, 117, 116, 32, 116, 104, 97, 116, 32, 116, 104, 101, 32, 100, 114, 101, 97, 100, 32, 111, 102, 32, 115, 111, 109, 101, 116, 104, 105, 110, 103, 32, 97, 102, 116, 101, 114, 32, 100, 101, 97, 116, 104, 44, 45, 45, 10, 84, 104, 101, 32, 117, 110, 100, 105, 115, 99, 111, 118, 101, 114, 39, 100, 32, 99, 111, 117, 110, 116, 114, 121, 44, 32, 102, 114, 111, 109, 32, 119, 104, 111, 115, 101, 32, 98, 111, 117, 114, 110, 10, 78, 111, 32, 116, 114, 97, 118, 101, 108, 108, 101, 114, 32, 114, 101, 116, 117, 114, 110, 115, 44, 45, 45, 112, 117, 122, 122, 108, 101, 115, 32, 116, 104, 101, 32, 119, 105, 108, 108, 44, 10, 65, 110, 100, 32, 109, 97, 107, 101, 115, 32, 117, 115, 32, 114, 97, 116, 104, 101, 114, 32, 98, 101, 97, 114, 32, 116, 104, 111, 115, 101, 32, 105, 108, 108, 115, 32, 119, 101, 32, 104, 97, 118, 101, 10, 84, 104, 97, 110, 32, 102, 108, 121, 32, 116, 111, 32, 111, 116, 104, 101, 114, 115, 32, 116, 104, 97, 116, 32, 119, 101, 32, 107, 110, 111, 119, 32, 110, 111, 116, 32, 111, 102, 63, 10, 84, 104, 117, 115, 32, 99, 111, 110, 115, 99, 105, 101, 110, 99, 101, 32, 100, 111, 101, 115, 32, 109, 97, 107, 101, 32, 99, 111, 119, 97, 114, 100, 115, 32, 111, 102, 32, 117, 115, 32, 97, 108, 108, 59, 10, 65, 110, 100, 32, 116, 104, 117, 115, 32, 116, 104, 101, 32, 110, 97, 116, 105, 118, 101, 32, 104, 117, 101, 32, 111, 102, 32, 114, 101, 115, 111, 108, 117, 116, 105, 111, 110, 10, 73, 115, 32, 115, 105, 99, 107, 108, 105, 101, 100, 32, 111, 39, 101, 114, 32, 119, 105, 116, 104, 32, 116, 104, 101, 32, 112, 97, 108, 101, 32, 99, 97, 115, 116, 32, 111, 102, 32, 116, 104, 111, 117, 103, 104, 116, 59, 10, 65, 110, 100, 32, 101, 110, 116, 101, 114, 112, 114, 105, 115, 101, 115, 32, 111, 102, 32, 103, 114, 101, 97, 116, 32, 112, 105, 116, 104, 32, 97, 110, 100, 32, 109, 111, 109, 101, 110, 116, 44, 10, 87, 105, 116, 104, 32, 116, 104, 105, 115, 32, 114, 101, 103, 97, 114, 100, 44, 32, 116, 104, 101, 105, 114, 32, 99, 117, 114, 114, 101, 110, 116, 115, 32, 116, 117, 114, 110, 32, 97, 119, 114, 121, 44, 10, 65, 110, 100, 32, 108, 111, 115, 101, 32, 116, 104, 101, 32, 110, 97, 109, 101, 32, 111, 102, 32, 97, 99, 116, 105, 111, 110, 46, 45, 45, 83, 111, 102, 116, 32, 121, 111, 117, 32, 110, 111, 119, 33, 10, 84, 104, 101, 32, 102, 97, 105, 114, 32, 79, 112, 104, 101, 108, 105, 97, 33, 45, 45, 78, 121, 109, 112, 104, 44, 32, 105, 110, 32, 116, 104, 121, 32, 111, 114, 105, 115, 111, 110, 115, 10, 66, 101, 32, 97, 108, 108, 32, 109, 121, 32, 115, 105, 110, 115, 32, 114, 101, 109, 101, 109, 98, 101, 114, 39, 100, 46, 10, 0, } var ( prefixMD5Crypt = []byte("$1$") prefixSHA1Crypt = []byte("$sha1$") prefixSunMD5Crypt = []byte("$md5$") prefixSunMD5CryptRounds = []byte("$md5,rounds=") sepCrypt = []byte("$") ) x-0.4.9/crypt/crypt.go000066400000000000000000000122631510400112300146130ustar00rootroot00000000000000package crypt import ( "crypto/hmac" "crypto/md5" "crypto/sha1" "crypto/sha256" "crypto/sha512" "hash" "strconv" ) // KeySHACrypt calculates the shacrypt SHA256/SHA512 key given an appropriate hash.Hash, password, salt, and number of rounds. func KeySHACrypt(hashFunc func() hash.Hash, password, salt []byte, rounds int) []byte { // Step 1. digest := hashFunc() size := digest.Size() switch size { case sha1.Size: return KeySHA1Crypt(password, salt, uint32(rounds)) case sha256.Size, sha512.Size: break default: return nil } length := len(password) // Step 2. digest.Write(password) // Step 3. digest.Write(salt) // Step 4. digestB := hashFunc() // Step 5. digestB.Write(password) // Step 6. digestB.Write(salt) // Step 7. digestB.Write(password) // Step 8. sumB := digestB.Sum(nil) digestB.Reset() digestB = nil // Step 9 and 10: digest.Write(repeat(sumB, length)) // Step 11. for i := length; i > 0; i >>= 1 { if even(i) { digest.Write(password) } else { digest.Write(sumB) } } clean(sumB) sumB = nil // Step 12. sumA := digest.Sum(nil) digest.Reset() // Step 13-14. for i := 0; i < length; i++ { digest.Write(password) } // Step 15. sumDP := digest.Sum(nil) digest.Reset() // Step 16. seqP := repeat(sumDP, length) sumDP = nil // Step 17-18. for i := 0; i < 16+int(sumA[0]); i++ { digest.Write(salt) } // Step 19. sumDS := digest.Sum(nil) digest.Reset() // Step 20. seqS := repeat(sumDS, len(salt)) // Step 21. for i := 0; i < rounds; i++ { digest.Reset() // Step 21 Sub-Step B and C. if i&1 != 0 { // Step 21 Sub-Step B. digest.Write(seqP) } else { // Step 21 Sub-Step C. digest.Write(sumA) } // Step 21 Sub-Step D. if i%3 != 0 { digest.Write(seqS) } // Step 21 Sub-Step E. if i%7 != 0 { digest.Write(seqP) } // Step 21 Sub-Step F and G. if i&1 != 0 { // Step 21 Sub-Step F. digest.Write(sumA) } else { // Step 21 Sub-Step G. digest.Write(seqP) } // Sub-Step H. copy(sumA, digest.Sum(nil)) } digest.Reset() digest = nil seqP, seqS = nil, nil switch size { case sha256.Size: // Step 22 Sub Step E. return permute(sumA, permuteTableSHACryptSHA256[:]) case sha512.Size: // Step 22 Sub Step E. return permute(sumA, permuteTableSHACryptSHA512[:]) } return nil } // KeySHA1Crypt calculates the sha1crypt key given a password, salt, and number of rounds. func KeySHA1Crypt(password, salt []byte, rounds uint32) []byte { digest := hmac.New(sha1.New, password) digest.Write(salt) digest.Write(prefixSHA1Crypt) digest.Write([]byte(strconv.FormatUint(uint64(rounds), 10))) sumA := digest.Sum(nil) if rounds == 0 { return permute(sumA, permuteTableSHA1Crypt[:]) } for rounds--; rounds > 0; rounds-- { digest.Reset() digest.Write(sumA) copy(sumA, digest.Sum(nil)) } return permute(sumA, permuteTableSHA1Crypt[:]) } // KeyMD5Crypt calculates the md5crypt key given a password and salt. func KeyMD5Crypt(password, salt []byte) []byte { length := len(password) digest := md5.New() digest.Write(password) digest.Write(salt) digest.Write(password) sumB := digest.Sum(nil) digest.Reset() digest.Write(password) digest.Write(prefixMD5Crypt) digest.Write(salt) digest.Write(repeat(sumB, length)) clean(sumB) for i := length; i > 0; i >>= 1 { if even(i) { digest.Write(password[0:1]) } else { digest.Write([]byte{0}) } } sumA := digest.Sum(nil) for i := 0; i < 1000; i++ { digest.Reset() if even(i) { digest.Write(sumA) } else { digest.Write(password) } if i%3 != 0 { digest.Write(salt) } if i%7 != 0 { digest.Write(password) } if i&1 == 0 { digest.Write(password) } else { digest.Write(sumA) } copy(sumA, digest.Sum(nil)) } return permute(sumA, permuteTableMD5Crypt[:]) } // KeyMD5CryptSun calculates the md5crypt (Sun Version) key given a password, salt, and number rounds. func KeyMD5CryptSun(password, salt []byte, rounds uint32) []byte { digest := md5.New() digest.Write(password) if rounds == 0 { digest.Write(prefixSunMD5Crypt) digest.Write(salt) digest.Write(sepCrypt) } else { digest.Write(prefixSunMD5CryptRounds) digest.Write([]byte(strconv.FormatUint(uint64(rounds), 10))) digest.Write(sepCrypt) digest.Write(salt) digest.Write(sepCrypt) } sumA := digest.Sum(nil) iterations := uint32(rounds + 4096) bit := func(off uint32) uint32 { off %= 128 if (sumA[off/8] & (0x01 << (off % 8))) != 0 { return 1 } return 0 } var ind7 [md5.Size]byte for i := uint32(0); i < iterations; i++ { digest.Reset() digest.Write(sumA) for j := 0; j < md5.Size; j++ { off := (j + 3) % 16 ind4 := (sumA[j] >> (sumA[off] % 5)) & 0x0F sh7 := (sumA[off] >> (sumA[j] % 8)) & 0x01 ind7[j] = (sumA[ind4] >> sh7) & 0x7F } var indA, indB uint32 for j := uint(0); j < 8; j++ { indA |= bit(uint32(ind7[j])) << j indB |= bit(uint32(ind7[j+8])) << j } indA = (indA >> bit(i)) & 0x7F indB = (indB >> bit(i+64)) & 0x7F if bit(indA)^bit(indB) == 1 { digest.Write(magicTableMD5CryptSunHamlet[:]) } digest.Write([]byte(strconv.FormatUint(uint64(i), 10))) copy(sumA, digest.Sum(nil)) } return permute(sumA, permuteTableMD5Crypt[:]) } x-0.4.9/crypt/util.go000066400000000000000000000013541510400112300144260ustar00rootroot00000000000000package crypt import ( b64 "github.com/go-crypt/x/base64" ) func permute(sum, table []byte) []byte { size := len(table) key := make([]byte, size) for i := 0; i < size; i++ { key[i] = sum[table[i]] } return b64.EncodeCrypt(key) } func even(i int) bool { return i%2 == 0 } var ( cleanBytes = make([]byte, 64) ) func clean(b []byte) { l := len(b) for ; l > 64; l -= 64 { copy(b[l-64:l], cleanBytes) } if l > 0 { copy(b[0:l], cleanBytes[0:l]) } } func repeat(input []byte, length int) []byte { var ( seq = make([]byte, length) unit = len(input) ) j := length / unit * unit for i := 0; i < j; i += unit { copy(seq[i:length], input) } if j < length { copy(seq[j:length], input[0:length-j]) } return seq } x-0.4.9/go.mod000066400000000000000000000004331510400112300130640ustar00rootroot00000000000000module github.com/go-crypt/x go 1.24.0 toolchain go1.25.4 require ( github.com/stretchr/testify v1.11.1 golang.org/x/sys v0.38.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) x-0.4.9/go.sum000066400000000000000000000020141510400112300131060ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= x-0.4.9/ldap/000077500000000000000000000000001510400112300126765ustar00rootroot00000000000000x-0.4.9/ldap/ldap.go000066400000000000000000000007041510400112300141460ustar00rootroot00000000000000package ldap import ( "bytes" "hash" ) // Key returns the RFC2307 key for the provided password and optional salt. Generally this is encoded with base64. func Key(hashFunc func() hash.Hash, password, salt []byte) []byte { s := len(salt) != 0 digest := hashFunc() digest.Write(password) if s { digest.Write(salt) } buf := &bytes.Buffer{} buf.Write(digest.Sum(nil)) digest.Reset() if s { buf.Write(salt) } return buf.Bytes() } x-0.4.9/pbkdf2/000077500000000000000000000000001510400112300131265ustar00rootroot00000000000000x-0.4.9/pbkdf2/README.md000066400000000000000000000001521510400112300144030ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/7b82a4e95df4499652dca2c0d4185de9fffbdc8f/pbkdf2 x-0.4.9/pbkdf2/pbkdf2.go000066400000000000000000000046141510400112300146320ustar00rootroot00000000000000// 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 ( "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] } x-0.4.9/pbkdf2/pbkdf2_test.go000066400000000000000000000070671510400112300156760ustar00rootroot00000000000000// 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) } x-0.4.9/scrypt/000077500000000000000000000000001510400112300133025ustar00rootroot00000000000000x-0.4.9/scrypt/README.md000066400000000000000000000002361510400112300145620ustar00rootroot00000000000000## Status Source: https://github.com/golang/crypto/tree/7b82a4e95df4499652dca2c0d4185de9fffbdc8f/scrypt https://github.com/golang/crypto/tree/master/scrypt x-0.4.9/scrypt/example_test.go000066400000000000000000000012151510400112300163220ustar00rootroot00000000000000// 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" "github.com/go-crypt/x/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= } x-0.4.9/scrypt/scrypt.go000066400000000000000000000131441510400112300151600ustar00rootroot00000000000000// 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 ( "crypto/sha256" "encoding/binary" "errors" "math/bits" "github.com/go-crypt/x/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 } x-0.4.9/scrypt/scrypt_test.go000066400000000000000000000106021510400112300162130ustar00rootroot00000000000000// 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) } } x-0.4.9/yescrypt/000077500000000000000000000000001510400112300136405ustar00rootroot00000000000000x-0.4.9/yescrypt/LICENSE000066400000000000000000000030041510400112300146420ustar00rootroot00000000000000Copyright (c) 2009-2020 The Go Authors. All rights reserved. Copyright (c) 2024 Solar Designer. 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. x-0.4.9/yescrypt/README.md000066400000000000000000000002361510400112300151200ustar00rootroot00000000000000## Status Source: https://github.com/openwall/yescrypt-go/blob/25b8ddb667c08550c094763c9c7e1cef6d9138ed/yescrypt.go https://github.com/openwall/yescrypt-go x-0.4.9/yescrypt/yescrypt.go000066400000000000000000000220171510400112300160530ustar00rootroot00000000000000// Copyright 2012-2020 The Go Authors. All rights reserved. // Copyright 2024 Solar Designer. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package yescrypt implements the scrypt key derivation function as defined in // Colin Percival's paper "Stronger Key Derivation via Sequential Memory-Hard // Functions", as well as Solar Designer's yescrypt. // yescrypt support sponsored by Sandfly Security https://sandflysecurity.com - // Agentless Security for Linux package yescrypt import ( "crypto/hmac" "crypto/sha256" "encoding/binary" "errors" "math/bits" "github.com/go-crypt/x/pbkdf2" ) const maxInt = int(^uint(0) >> 1) // blockCopy copies n numbers from src into dst. func blockCopy(dst, src []uint64, n int) { copy(dst, src[:n]) } // blockXOR XORs numbers from dst with n numbers from src. func blockXOR(dst, src []uint64, 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 *[8]uint64, in, out []uint64, rounds int) { d0 := tmp[0] ^ in[0] d1 := tmp[1] ^ in[1] d2 := tmp[2] ^ in[2] d3 := tmp[3] ^ in[3] d4 := tmp[4] ^ in[4] d5 := tmp[5] ^ in[5] d6 := tmp[6] ^ in[6] d7 := tmp[7] ^ in[7] x0, x1 := uint32(d0), uint32(d6>>32) x2, x3 := uint32(d5), uint32(d3>>32) x4, x5 := uint32(d2), uint32(d0>>32) x6, x7 := uint32(d7), uint32(d5>>32) x8, x9 := uint32(d4), uint32(d2>>32) x10, x11 := uint32(d1), uint32(d7>>32) x12, x13 := uint32(d6), uint32(d4>>32) x14, x15 := uint32(d3), uint32(d1>>32) for i := 0; i < rounds; 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) } d0 = uint64(uint32(d0)+x0) | uint64(uint32(d0>>32)+x5)<<32 d1 = uint64(uint32(d1)+x10) | uint64(uint32(d1>>32)+x15)<<32 d2 = uint64(uint32(d2)+x4) | uint64(uint32(d2>>32)+x9)<<32 d3 = uint64(uint32(d3)+x14) | uint64(uint32(d3>>32)+x3)<<32 d4 = uint64(uint32(d4)+x8) | uint64(uint32(d4>>32)+x13)<<32 d5 = uint64(uint32(d5)+x2) | uint64(uint32(d5>>32)+x7)<<32 d6 = uint64(uint32(d6)+x12) | uint64(uint32(d6>>32)+x1)<<32 d7 = uint64(uint32(d7)+x6) | uint64(uint32(d7>>32)+x11)<<32 out[0], tmp[0] = d0, d0 out[1], tmp[1] = d1, d1 out[2], tmp[2] = d2, d2 out[3], tmp[3] = d3, d3 out[4], tmp[4] = d4, d4 out[5], tmp[5] = d5, d5 out[6], tmp[6] = d6, d6 out[7], tmp[7] = d7, d7 } func blockMix(tmp *[8]uint64, in, out []uint64, r int) { blockCopy(tmp[:], in[(2*r-1)*8:], 8) for i := 0; i < 2*r; i += 2 { salsaXOR(tmp, in[i*8:], out[i*4:], 8) salsaXOR(tmp, in[i*8+8:], out[i*4+r*8:], 8) } } // These were tunable at design time, but they must meet certain constraints const ( PWXsimple = 2 PWXgather = 4 PWXrounds = 6 Swidth = 8 ) // Derived values. These were never tunable on their own. const ( PWXbytes = PWXgather * PWXsimple * 8 PWXwords = PWXbytes / 8 Sbytes = 3 * (1 << Swidth) * PWXsimple * 8 Swords = Sbytes / 8 Smask = (((1 << Swidth) - 1) * PWXsimple * 8) ) type pwxformCtx struct { S0, S1, S2 []uint64 w uint32 } func pwxform(X *[PWXwords]uint64, ctx *pwxformCtx) { S0, S1, S2, w := ctx.S0, ctx.S1, ctx.S2, ctx.w for i := 0; i < PWXrounds; i++ { for j := 0; j < PWXgather; j++ { // Unrolled inner loop for PWXsimple=2 x := X[j*PWXsimple] xl := uint32(x) xh := uint32(x >> 32) x = uint64(xh) * uint64(xl) xl = (xl & Smask) / 8 xh = (xh & Smask) / 8 x = (x + S0[xl]) ^ S1[xh] X[j*PWXsimple] = x y := X[j*PWXsimple+1] y = ((y>>32)*uint64(uint32(y)) + S0[xl+1]) ^ S1[xh+1] X[j*PWXsimple+1] = y if i != 0 && i != PWXrounds-1 { S2[w] = x S2[w+1] = y w += 2 } } } ctx.S0, ctx.S1, ctx.S2 = S2, S0, S1 ctx.w = w & ((1< 1 { j := int(wrap(integer(x, r), uint32(i))) blockXOR(x, v[j*R:], R) } blockMixPwxform(&tmp, x, r, ctx) } for i := 0; i < Nloop; i++ { j := int(integer(x, r) & uint32(N-1)) blockXOR(x, v[j*R:], R) blockCopy(v[j*R:], x, R) blockMixPwxform(&tmp, x, r, ctx) } } else { 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 < Nloop; i += 2 { j := int(integer(x, r) & uint32(N-1)) blockXOR(x, v[j*R:], R) blockMix(&tmp, x, y, r) j = int(integer(y, r) & uint32(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 & ^63)|((j*5)&63):], uint32(v)) j += 4 binary.LittleEndian.PutUint32(b[(j & ^63)|((j*5)&63):], uint32(v>>32)) j += 4 } } func smixYescrypt(b []byte, r, N int, v, xy []uint64, passwordSha256 []byte) { var ctx pwxformCtx var S [Swords]uint64 smix(b, 1, Sbytes/128, 0, S[:], xy, nil) ctx.S2 = S[:] ctx.S1 = S[(1< 1 and a power of 2") } if r <= 0 { return nil, errors.New("yescrypt: r must be > 0") } if p != 1 { return nil, errors.New("yescrypt: p must be 1") } if uint64(r)*uint64(p) >= 1<<30 || r > maxInt/128/p || r > maxInt/256 || N > maxInt/128/r { return nil, errors.New("(ye)scrypt: parameters are too large") } ppassword := &password pass := 1 prehash := []byte("yescrypt-prehash") v := make([]uint64, 16*N*r) var key []byte xy := make([]uint64, 16*max(r, 2)) if N/p >= 0x100 && N/p*r >= 0x20000 { pass = 0 N >>= 6 } for pass <= 1 { if pass == 1 { prehash = prehash[:8] } h := hmac.New(sha256.New, prehash) h.Write(*ppassword) passwordSha256 := h.Sum(nil) ppassword = &passwordSha256 b := pbkdf2.Key(*ppassword, salt, 1, p*128*r, sha256.New) copy(*ppassword, b[:32]) smixYescrypt(b, r, N, v, xy, *ppassword) key = pbkdf2.Key(*ppassword, b, 1, max(keyLen, 32), sha256.New) if pass == 0 { copy(*ppassword, key[:32]) N <<= 6 } else { h1 := hmac.New(sha256.New, key[:32]) h1.Write([]byte("Client Key")) h2 := sha256.New() h2.Write(h1.Sum(nil)) copy(key, h2.Sum(nil)) } pass++ } return key[:keyLen], nil } // Key computes native yescrypt assuming reference yescrypt's current default // flags (as of yescrypt 1.1.0), p=1 (which it currently requires), t=0, and no // ROM. Example usage: // // dk, err := yescrypt.Key([]byte("some password"), salt, 32768, 8, 1, 32) // // The set of parameters accepted by Key will likely change in future versions // of this Go module to support more yescrypt functionality. func Key(password, salt []byte, N, r, p, keyLen int) ([]byte, error) { return deriveKey(password, salt, N, r, p, keyLen) } x-0.4.9/yescrypt/yescrypt_encoding.go000066400000000000000000000040451510400112300177220ustar00rootroot00000000000000package yescrypt import ( "errors" ) const itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" var atoi64Partial = [...]byte{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 64, 64, 64, 64, 64, 64, 64, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 64, 64, 64, 64, 64, 64, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, } func atoi64(c byte) int { if c >= '.' && c <= 'z' { return int(atoi64Partial[c-'.']) } return 64 } func byteEncode64(src byte) byte { return itoa64[src&0x3f] } func Encode64(src []byte) []byte { dst := make([]byte, 0, (len(src)*8+5)/6) for i := 0; i < len(src); { value, bits := uint32(0), 0 for ; bits < 24 && i < len(src); bits += 8 { value |= uint32(src[i]) << bits i++ } for ; bits > 0; bits -= 6 { dst = append(dst, itoa64[value&0x3f]) value >>= 6 } } return dst } func Decode64(src []byte) []byte { dst := make([]byte, 0, len(src)*3/4) for i := 0; i < len(src); { value, bits := uint32(0), uint32(0) for ; bits < 24 && i < len(src); bits += 6 { c := atoi64(src[i]) if c > 63 { return nil } i++ value |= uint32(c) << bits } if bits < 12 { // Must have at least one full byte return nil } for ; bits >= 8; bits -= 8 { dst = append(dst, byte(value)) value >>= 8 } if value != 0 { // May have 2 or 4 bits left, which must be 0 return nil } } return dst } func EncodeSetting(flags, ln, r int) []byte { // TODO: Properly handle flags instead of hardcoding 'j'. return []byte("j" + string(byteEncode64(byte(ln-1))) + string(byteEncode64(byte(r-1)))) } func DecodeSetting(setting []byte) (flags, ln, r int, err error) { if len(setting) != 3 { return 0, 0, 0, errors.New("yescrypt: bad setting") } // TODO: Properly handle flags. if setting[0] != byte(106) { return 0, 0, 0, errors.New("yescrypt: bad setting") } // TODO: Properly handle flags. return 182, atoi64(setting[1]) + 1, atoi64(setting[2]) + 1, nil } x-0.4.9/yescrypt/yescrypt_test.go000066400000000000000000000145561510400112300171230ustar00rootroot00000000000000// Copyright 2012-2017 The Go Authors. All rights reserved. // Copyright 2024 Solar Designer. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // yescrypt support sponsored by Sandfly Security https://sandflysecurity.com - // Agentless Security for Linux package yescrypt import ( "bytes" "testing" ) type testVector struct { password string salt string N, r, p int output []byte } var good = []testVector{ { "p", "s", 16, 8, 1, []byte{ 0xc8, 0xc7, 0xff, 0x11, 0x22, 0xb0, 0xb2, 0x91, 0xc3, 0xf2, 0x60, 0x89, 0x48, 0x78, 0x2c, 0xd6, 0x89, 0xcc, 0x45, 0x57, 0x90, 0x17, 0xaa, 0xa5, 0xff, 0x8b, 0xaa, 0x74, 0xa6, 0x32, 0xec, 0x99, }, }, { "p", "s", 16, 8, 1, []byte{ 0xc8, 0xc7, 0xff, 0x11, 0x22, 0xb0, 0xb2, 0x91, }, }, { "", "", 4, 1, 1, []byte{ 0x0c, 0xd5, 0xaf, 0x76, 0xeb, 0x24, 0x1d, 0xf8, 0x11, 0x9a, 0x9a, 0x12, 0x2a, 0xe3, 0x69, 0x20, 0xbc, 0xc7, 0xf4, 0x14, 0xb9, 0xc0, 0xd5, 0x8f, 0x45, 0x00, 0x80, 0x60, 0xda, 0xde, 0x46, 0xb0, 0xc8, 0x09, 0x22, 0xbd, 0xcc, 0x16, 0xa3, 0xab, }, }, } 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 {"p", "s", 16, 0, 1, nil}, // r too small {"p", "s", 16, 1, 0, nil}, // p too small { "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, }, }, } 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 type testVectorHash struct { password string hash string } /* Generated with: #include #include int main(void) { for (int count = 1; count <= 11; count++) { const char *setting = crypt_gensalt("$y$", count, NULL, 0); char pw[8]; snprintf(pw, sizeof(pw), "test%d", count); printf("\t{\"%s\", \"%s\"},\n", pw, crypt(pw, setting)); } for (int saltlen = 0; saltlen <= 24; saltlen++) { char pw[16], setting[32]; snprintf(pw, sizeof(pw), "salt length %d", saltlen); snprintf(setting, sizeof(setting), "$y$j7.$%.*s", saltlen, "////////////////////////"); printf("\t{\"%s\", \"%s\"},\n", pw, crypt(pw, setting) ?: setting); } return 0; } */ var hashes = []testVectorHash{ {"test1", "$y$j75$z7ztFz2FayrKI79/jEwlL.$u5x/j193MQ09wbFaRGYr0AH/A/jh3kunjuhYRVRNkmC"}, {"test2", "$y$j85$uFLpki6/G99e8OAxVooij1$64Rji3LKk1v85LYVULHKh2YKeKoDu0ADrGt4l1JhQy8"}, {"test3", "$y$j7T$aoovSEloTaFiZVMrFisfy.$wLTAPbITTB/XIpAGwcX0xxRCFEcDgPWpXTsij0SEbC5"}, {"test4", "$y$j8T$P9xODwGnzlle5VHuP1/qA1$bAd4BXv1GBqNQZFzR0Ey42/w0/DFmnFkX1fRpjalAO2"}, {"test5", "$y$j9T$fqIAg4Vpv9o1MKgWMnyax.$BxkUx27fLJlPOfyIfNEBPzjrDQ95LXKgN5OJii3GL7."}, {"test6", "$y$jAT$70Rw91iJgO8Uzi3CLWfOo1$aYky8YP.XurVMdZfcXHY1do2RZ7Caav5iliKEkmJjhD"}, {"test7", "$y$jBT$/YBmADVZsSMw3xfv8M76X0$14s2oH3zHEKh44d5eRVxmDvF8jgM/8SXd8mI4NBQIS1"}, /* {"test8", "$y$jCT$JXJjOzzWl5vilbjjonN5N1$.HyIln8Y5//hXrEaSMIFPSHBAE24eR392XzBtFELSv9"}, {"test9", "$y$jDT$pPCKQ.Jzpv90Nh7H.ioA9/$6fSLU.2dsGXHY1DZuRncQtItRzZNx9oClKgMpSEkyW0"}, {"test10", "$y$jET$YA8uEtDHnx9Sv9OvDcwv81$zfxVIsTgxs6v/qL.nTBEE.o9du75wuSHnF5Sai6K.s7"}, {"test11", "$y$jFT$c1pwXe.GpcUUeOK7BV6yX1$lys4J0.caCkYP6ZpfUj.2zuJAiTpMFj0O9HhN59/QI."}, */ {"salt length 0", "$y$j7.$$cmp7v9bzgyAhctAaiyqG56MBYN2IYzfI5LvybJCKacD"}, {"salt length 1", "$y$j7.$/"}, {"salt length 2", "$y$j7.$//$DcruwIS63Fs/rFjEN0XX6h83bZyXgBTDICvINmSWVp5"}, {"salt length 3", "$y$j7.$///$uo0SD4Xn0Bn1leZVH50teLu3Rje5GAIA.BKYA/jL3/C"}, {"salt length 4", "$y$j7.$////$WXGIKO.4sthsRPnpY0/.OhyrlEkLcS1pymEGTbJA/l."}, {"salt length 5", "$y$j7.$/////"}, {"salt length 6", "$y$j7.$//////$9/wDzXoL4.VS3Ztb.NPiOu4wTpTBKrnJTxBwH1fK70A"}, {"salt length 7", "$y$j7.$///////$iFpkxOqqnskGorbt2d.daPYT2vUWCRsisu0jr4sNF1."}, {"salt length 8", "$y$j7.$////////$caDf7LpLxRuDzYqMUDha1Nvm9zX2M89hTuCi.33hpMA"}, {"salt length 9", "$y$j7.$/////////"}, {"salt length 10", "$y$j7.$//////////$w8.ijckeAcw8QTQFtNDzf6GAbpM0GS1tPF9.moe8DA6"}, {"salt length 11", "$y$j7.$///////////$aNlOwAA3WuQ2GScDBr/fTD34oO0ZN/BksJ8d6ilH4O8"}, {"salt length 12", "$y$j7.$////////////$9YMdFtGt/uJi6XsLbYVhRfnneKsMgoos2r.7fZ8Xn.."}, {"salt length 13", "$y$j7.$/////////////"}, {"salt length 14", "$y$j7.$//////////////$fPBNb956TRLinNI/LHoThcqdVO5gIGIg/nRpmyzB/T/"}, {"salt length 15", "$y$j7.$///////////////$lzaOauYlT250iKS8qtIlo8Ail.PbSHjKSjRpPsEqcI6"}, {"salt length 16", "$y$j7.$////////////////$DlYtorMMW/M1IdFxGPdfFS.STo61kYy/eHnOanwVvrC"}, {"salt length 17", "$y$j7.$/////////////////"}, {"salt length 18", "$y$j7.$//////////////////$3P/0DYS.t.P2VC4rnF9kWURChONU4ehShDJyGUIoYZ9"}, {"salt length 19", "$y$j7.$///////////////////$.M.DTam6fr/7j36F7Mo0g3QGSYAD7PbZkwe8X9bJyd8"}, {"salt length 20", "$y$j7.$////////////////////$dHX43Z/x85XNKoOu4UDromlyoPcD9isScOP8ZeW6l27"}, {"salt length 21", "$y$j7.$/////////////////////"}, {"salt length 22", "$y$j7.$//////////////////////$XXf4WJAUsQCV6TUulO3H/f3OWOuK8j8FX9ZtJluydw4"}, {"salt length 23", "$y$j7.$///////////////////////$FOmK9/DdyesVtGrimp4GNqRPMQ5V6Z8/wfRPWZ.XhjA"}, {"salt length 24", "$y$j7.$////////////////////////$xW7NvvbWPmxoFVWCDe.WNwrrSfuN/iVvy/05.lD/MO9"}, // More expected errors {"", ""}, {"", "$y$.7.$$"}, {"", "$y$j..$$"}, } func TestHash(t *testing.T) { for i, v := range hashes { cut := len(v.hash) if cut > 29 && (i&1) != 0 { cut = 29 + i/2 } hash, err := Hash([]byte(v.password), []byte(v.hash)[:cut]) if len(hash) < 51 { if err == nil { t.Errorf("%d: expected error, got %s, nil", i, hash) } continue } if err != nil { t.Errorf("Hash %d: got unexpected error: %s", i, err) } if string(hash) != v.hash { t.Errorf("Hash %d: expected %s, got %s", i, v.hash, hash) } } } x-0.4.9/yescrypt/yescrypt_wrapper.go000066400000000000000000000034241510400112300176140ustar00rootroot00000000000000// Copyright 2024 Solar Designer. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Alternatively, this specific source file is also available under more // relaxed terms (0-clause BSD license): // Redistribution and use in source and binary forms, with or without // modification, are permitted. // yescrypt support sponsored by Sandfly Security https://sandflysecurity.com - // Agentless Security for Linux package yescrypt import ( "bytes" "errors" ) // Hash computes yescrypt hash encoding given the password and existing yescrypt // setting or full hash encoding. The salt and other parameters are decoded // from setting. Currently supports (only a little more than) the subset of // yescrypt parameters that libxcrypt can generate (as of libxcrypt 4.4.36). func Hash(password, setting []byte) ([]byte, error) { if len(setting) < 7 || string(setting[:4]) != "$y$j" || setting[6] != '$' { return nil, errors.New("yescrypt: unsupported parameters") } // Proper yescrypt uses variable-length integers // We take a shortcut approach that works in a more limited range Nlog2 := atoi64(setting[4]) + 1 if Nlog2 < 10 || Nlog2 > 18 { return nil, errors.New("yescrypt: N out of supported range") } r := atoi64(setting[5]) + 1 if r < 1 || r > 32 { return nil, errors.New("yescrypt: r out of supported range") } saltEnd := bytes.LastIndexByte(setting, '$') if saltEnd < 7 { saltEnd = len(setting) } salt := Decode64(setting[7:saltEnd]) if salt == nil { return nil, errors.New("yescrypt: bad salt encoding") } key, err := Key(password, salt, 1<