Integrate BACKBEAT SDK and resolve KACHING license validation
Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
		
							
								
								
									
										1
									
								
								vendor/github.com/flynn/noise/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/flynn/noise/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| See the [Flynn contributing guide](https://flynn.io/docs/contributing). | ||||
							
								
								
									
										29
									
								
								vendor/github.com/flynn/noise/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/flynn/noise/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| Flynn® is a trademark of Prime Directive, Inc. | ||||
|  | ||||
| Copyright (c) 2015 Prime Directive, Inc. 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 Prime Directive, 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. | ||||
							
								
								
									
										5
									
								
								vendor/github.com/flynn/noise/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/flynn/noise/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| # noise [](https://pkg.go.dev/github.com/flynn/noise) [](https://github.com/flynn/noise/actions) | ||||
|  | ||||
| This is a Go package that implements the [Noise Protocol | ||||
| Framework](https://noiseprotocol.org). See [the | ||||
| documentation](https://pkg.go.dev/github.com/flynn/noise) for usage information. | ||||
							
								
								
									
										224
									
								
								vendor/github.com/flynn/noise/cipher_suite.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								vendor/github.com/flynn/noise/cipher_suite.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| package noise | ||||
|  | ||||
| import ( | ||||
| 	"crypto/aes" | ||||
| 	"crypto/cipher" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/sha256" | ||||
| 	"crypto/sha512" | ||||
| 	"encoding/binary" | ||||
| 	"hash" | ||||
| 	"io" | ||||
|  | ||||
| 	"golang.org/x/crypto/blake2b" | ||||
| 	"golang.org/x/crypto/blake2s" | ||||
| 	"golang.org/x/crypto/chacha20poly1305" | ||||
| 	"golang.org/x/crypto/curve25519" | ||||
| ) | ||||
|  | ||||
| // A DHKey is a keypair used for Diffie-Hellman key agreement. | ||||
| type DHKey struct { | ||||
| 	Private []byte | ||||
| 	Public  []byte | ||||
| } | ||||
|  | ||||
| // A DHFunc implements Diffie-Hellman key agreement. | ||||
| type DHFunc interface { | ||||
| 	// GenerateKeypair generates a new keypair using random as a source of | ||||
| 	// entropy. | ||||
| 	GenerateKeypair(random io.Reader) (DHKey, error) | ||||
|  | ||||
| 	// DH performs a Diffie-Hellman calculation between the provided private and | ||||
| 	// public keys and returns the result. | ||||
| 	DH(privkey, pubkey []byte) ([]byte, error) | ||||
|  | ||||
| 	// DHLen is the number of bytes returned by DH. | ||||
| 	DHLen() int | ||||
|  | ||||
| 	// DHName is the name of the DH function. | ||||
| 	DHName() string | ||||
| } | ||||
|  | ||||
| // A HashFunc implements a cryptographic hash function. | ||||
| type HashFunc interface { | ||||
| 	// Hash returns a hash state. | ||||
| 	Hash() hash.Hash | ||||
|  | ||||
| 	// HashName is the name of the hash function. | ||||
| 	HashName() string | ||||
| } | ||||
|  | ||||
| // A CipherFunc implements an AEAD symmetric cipher. | ||||
| type CipherFunc interface { | ||||
| 	// Cipher initializes the algorithm with the provided key and returns a Cipher. | ||||
| 	Cipher(k [32]byte) Cipher | ||||
|  | ||||
| 	// CipherName is the name of the cipher. | ||||
| 	CipherName() string | ||||
| } | ||||
|  | ||||
| // A Cipher is a AEAD cipher that has been initialized with a key. | ||||
| type Cipher interface { | ||||
| 	// Encrypt encrypts the provided plaintext with a nonce and then appends the | ||||
| 	// ciphertext to out along with an authentication tag over the ciphertext | ||||
| 	// and optional authenticated data. | ||||
| 	Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte | ||||
|  | ||||
| 	// Decrypt authenticates the ciphertext and optional authenticated data and | ||||
| 	// then decrypts the provided ciphertext using the provided nonce and | ||||
| 	// appends it to out. | ||||
| 	Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) | ||||
| } | ||||
|  | ||||
| // A CipherSuite is a set of cryptographic primitives used in a Noise protocol. | ||||
| // It should be constructed with NewCipherSuite. | ||||
| type CipherSuite interface { | ||||
| 	DHFunc | ||||
| 	CipherFunc | ||||
| 	HashFunc | ||||
| 	Name() []byte | ||||
| } | ||||
|  | ||||
| // NewCipherSuite returns a CipherSuite constructed from the specified | ||||
| // primitives. | ||||
| func NewCipherSuite(dh DHFunc, c CipherFunc, h HashFunc) CipherSuite { | ||||
| 	return ciphersuite{ | ||||
| 		DHFunc:     dh, | ||||
| 		CipherFunc: c, | ||||
| 		HashFunc:   h, | ||||
| 		name:       []byte(dh.DHName() + "_" + c.CipherName() + "_" + h.HashName()), | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type ciphersuite struct { | ||||
| 	DHFunc | ||||
| 	CipherFunc | ||||
| 	HashFunc | ||||
| 	name []byte | ||||
| } | ||||
|  | ||||
| func (s ciphersuite) Name() []byte { return s.name } | ||||
|  | ||||
| // DH25519 is the Curve25519 ECDH function. | ||||
| var DH25519 DHFunc = dh25519{} | ||||
|  | ||||
| type dh25519 struct{} | ||||
|  | ||||
| func (dh25519) GenerateKeypair(rng io.Reader) (DHKey, error) { | ||||
| 	privkey := make([]byte, 32) | ||||
| 	if rng == nil { | ||||
| 		rng = rand.Reader | ||||
| 	} | ||||
| 	if _, err := io.ReadFull(rng, privkey); err != nil { | ||||
| 		return DHKey{}, err | ||||
| 	} | ||||
| 	pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint) | ||||
| 	if err != nil { | ||||
| 		return DHKey{}, err | ||||
| 	} | ||||
| 	return DHKey{Private: privkey, Public: pubkey}, nil | ||||
| } | ||||
|  | ||||
| func (dh25519) DH(privkey, pubkey []byte) ([]byte, error) { | ||||
| 	return curve25519.X25519(privkey, pubkey) | ||||
| } | ||||
|  | ||||
| func (dh25519) DHLen() int     { return 32 } | ||||
| func (dh25519) DHName() string { return "25519" } | ||||
|  | ||||
| type cipherFn struct { | ||||
| 	fn   func([32]byte) Cipher | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| func (c cipherFn) Cipher(k [32]byte) Cipher { return c.fn(k) } | ||||
| func (c cipherFn) CipherName() string       { return c.name } | ||||
|  | ||||
| // CipherAESGCM is the AES256-GCM AEAD cipher. | ||||
| var CipherAESGCM CipherFunc = cipherFn{cipherAESGCM, "AESGCM"} | ||||
|  | ||||
| func cipherAESGCM(k [32]byte) Cipher { | ||||
| 	c, err := aes.NewCipher(k[:]) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	gcm, err := cipher.NewGCM(c) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return aeadCipher{ | ||||
| 		gcm, | ||||
| 		func(n uint64) []byte { | ||||
| 			var nonce [12]byte | ||||
| 			binary.BigEndian.PutUint64(nonce[4:], n) | ||||
| 			return nonce[:] | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // CipherChaChaPoly is the ChaCha20-Poly1305 AEAD cipher construction. | ||||
| var CipherChaChaPoly CipherFunc = cipherFn{cipherChaChaPoly, "ChaChaPoly"} | ||||
|  | ||||
| func cipherChaChaPoly(k [32]byte) Cipher { | ||||
| 	c, err := chacha20poly1305.New(k[:]) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return aeadCipher{ | ||||
| 		c, | ||||
| 		func(n uint64) []byte { | ||||
| 			var nonce [12]byte | ||||
| 			binary.LittleEndian.PutUint64(nonce[4:], n) | ||||
| 			return nonce[:] | ||||
| 		}, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| type aeadCipher struct { | ||||
| 	cipher.AEAD | ||||
| 	nonce func(uint64) []byte | ||||
| } | ||||
|  | ||||
| func (c aeadCipher) Encrypt(out []byte, n uint64, ad, plaintext []byte) []byte { | ||||
| 	return c.Seal(out, c.nonce(n), plaintext, ad) | ||||
| } | ||||
|  | ||||
| func (c aeadCipher) Decrypt(out []byte, n uint64, ad, ciphertext []byte) ([]byte, error) { | ||||
| 	return c.Open(out, c.nonce(n), ciphertext, ad) | ||||
| } | ||||
|  | ||||
| type hashFn struct { | ||||
| 	fn   func() hash.Hash | ||||
| 	name string | ||||
| } | ||||
|  | ||||
| func (h hashFn) Hash() hash.Hash  { return h.fn() } | ||||
| func (h hashFn) HashName() string { return h.name } | ||||
|  | ||||
| // HashSHA256 is the SHA-256 hash function. | ||||
| var HashSHA256 HashFunc = hashFn{sha256.New, "SHA256"} | ||||
|  | ||||
| // HashSHA512 is the SHA-512 hash function. | ||||
| var HashSHA512 HashFunc = hashFn{sha512.New, "SHA512"} | ||||
|  | ||||
| func blake2bNew() hash.Hash { | ||||
| 	h, err := blake2b.New512(nil) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| // HashBLAKE2b is the BLAKE2b hash function. | ||||
| var HashBLAKE2b HashFunc = hashFn{blake2bNew, "BLAKE2b"} | ||||
|  | ||||
| func blake2sNew() hash.Hash { | ||||
| 	h, err := blake2s.New256(nil) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return h | ||||
| } | ||||
|  | ||||
| // HashBLAKE2s is the BLAKE2s hash function. | ||||
| var HashBLAKE2s HashFunc = hashFn{blake2sNew, "BLAKE2s"} | ||||
							
								
								
									
										49
									
								
								vendor/github.com/flynn/noise/hkdf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								vendor/github.com/flynn/noise/hkdf.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| package noise | ||||
|  | ||||
| import ( | ||||
| 	"crypto/hmac" | ||||
| 	"hash" | ||||
| ) | ||||
|  | ||||
| func hkdf(h func() hash.Hash, outputs int, out1, out2, out3, chainingKey, inputKeyMaterial []byte) ([]byte, []byte, []byte) { | ||||
| 	if len(out1) > 0 { | ||||
| 		panic("len(out1) > 0") | ||||
| 	} | ||||
| 	if len(out2) > 0 { | ||||
| 		panic("len(out2) > 0") | ||||
| 	} | ||||
| 	if len(out3) > 0 { | ||||
| 		panic("len(out3) > 0") | ||||
| 	} | ||||
| 	if outputs > 3 { | ||||
| 		panic("outputs > 3") | ||||
| 	} | ||||
|  | ||||
| 	tempMAC := hmac.New(h, chainingKey) | ||||
| 	tempMAC.Write(inputKeyMaterial) | ||||
| 	tempKey := tempMAC.Sum(out2) | ||||
|  | ||||
| 	out1MAC := hmac.New(h, tempKey) | ||||
| 	out1MAC.Write([]byte{0x01}) | ||||
| 	out1 = out1MAC.Sum(out1) | ||||
|  | ||||
| 	if outputs == 1 { | ||||
| 		return out1, nil, nil | ||||
| 	} | ||||
|  | ||||
| 	out2MAC := hmac.New(h, tempKey) | ||||
| 	out2MAC.Write(out1) | ||||
| 	out2MAC.Write([]byte{0x02}) | ||||
| 	out2 = out2MAC.Sum(out2) | ||||
|  | ||||
| 	if outputs == 2 { | ||||
| 		return out1, out2, nil | ||||
| 	} | ||||
|  | ||||
| 	out3MAC := hmac.New(h, tempKey) | ||||
| 	out3MAC.Write(out2) | ||||
| 	out3MAC.Write([]byte{0x03}) | ||||
| 	out3 = out3MAC.Sum(out3) | ||||
|  | ||||
| 	return out1, out2, out3 | ||||
| } | ||||
							
								
								
									
										141
									
								
								vendor/github.com/flynn/noise/patterns.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								vendor/github.com/flynn/noise/patterns.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| package noise | ||||
|  | ||||
| var HandshakeNN = HandshakePattern{ | ||||
| 	Name: "NN", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeKN = HandshakePattern{ | ||||
| 	Name:                 "KN", | ||||
| 	InitiatorPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeNK = HandshakePattern{ | ||||
| 	Name:                 "NK", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES}, | ||||
| 		{MessagePatternE, MessagePatternDHEE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeKK = HandshakePattern{ | ||||
| 	Name:                 "KK", | ||||
| 	InitiatorPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES, MessagePatternDHSS}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeNX = HandshakePattern{ | ||||
| 	Name: "NX", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHES}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeKX = HandshakePattern{ | ||||
| 	Name:                 "KX", | ||||
| 	InitiatorPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE, MessagePatternS, MessagePatternDHES}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeXN = HandshakePattern{ | ||||
| 	Name: "XN", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE}, | ||||
| 		{MessagePatternS, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeIN = HandshakePattern{ | ||||
| 	Name: "IN", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternS}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeXK = HandshakePattern{ | ||||
| 	Name:                 "XK", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES}, | ||||
| 		{MessagePatternE, MessagePatternDHEE}, | ||||
| 		{MessagePatternS, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeIK = HandshakePattern{ | ||||
| 	Name:                 "IK", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES, MessagePatternS, MessagePatternDHSS}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeXX = HandshakePattern{ | ||||
| 	Name: "XX", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHES}, | ||||
| 		{MessagePatternS, MessagePatternDHSE}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeXXfallback = HandshakePattern{ | ||||
| 	Name:                 "XXfallback", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternE}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternS, MessagePatternDHSE}, | ||||
| 		{MessagePatternS, MessagePatternDHES}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeIX = HandshakePattern{ | ||||
| 	Name: "IX", | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternS}, | ||||
| 		{MessagePatternE, MessagePatternDHEE, MessagePatternDHSE, MessagePatternS, MessagePatternDHES}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeN = HandshakePattern{ | ||||
| 	Name:                 "N", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeK = HandshakePattern{ | ||||
| 	Name:                 "K", | ||||
| 	InitiatorPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES, MessagePatternDHSS}, | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| var HandshakeX = HandshakePattern{ | ||||
| 	Name:                 "X", | ||||
| 	ResponderPreMessages: []MessagePattern{MessagePatternS}, | ||||
| 	Messages: [][]MessagePattern{ | ||||
| 		{MessagePatternE, MessagePatternDHES, MessagePatternS, MessagePatternDHSS}, | ||||
| 	}, | ||||
| } | ||||
							
								
								
									
										600
									
								
								vendor/github.com/flynn/noise/state.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										600
									
								
								vendor/github.com/flynn/noise/state.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,600 @@ | ||||
| // Package noise implements the Noise Protocol Framework. | ||||
| // | ||||
| // Noise is a low-level framework for building crypto protocols. Noise protocols | ||||
| // support mutual and optional authentication, identity hiding, forward secrecy, | ||||
| // zero round-trip encryption, and other advanced features. For more details, | ||||
| // visit https://noiseprotocol.org. | ||||
| package noise | ||||
|  | ||||
| import ( | ||||
| 	"crypto/rand" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| ) | ||||
|  | ||||
| // A CipherState provides symmetric encryption and decryption after a successful | ||||
| // handshake. | ||||
| type CipherState struct { | ||||
| 	cs CipherSuite | ||||
| 	c  Cipher | ||||
| 	k  [32]byte | ||||
| 	n  uint64 | ||||
|  | ||||
| 	invalid bool | ||||
| } | ||||
|  | ||||
| // MaxNonce is the maximum value of n that is allowed. ErrMaxNonce is returned | ||||
| // by Encrypt and Decrypt after this has been reached. 2^64-1 is reserved for rekeys. | ||||
| const MaxNonce = uint64(math.MaxUint64) - 1 | ||||
|  | ||||
| var ErrMaxNonce = errors.New("noise: cipherstate has reached maximum n, a new handshake must be performed") | ||||
| var ErrCipherSuiteCopied = errors.New("noise: CipherSuite has been copied, state is invalid") | ||||
|  | ||||
| // Encrypt encrypts the plaintext and then appends the ciphertext and an | ||||
| // authentication tag across the ciphertext and optional authenticated data to | ||||
| // out. This method automatically increments the nonce after every call, so | ||||
| // messages must be decrypted in the same order. ErrMaxNonce is returned after | ||||
| // the maximum nonce of 2^64-2 is reached. | ||||
| func (s *CipherState) Encrypt(out, ad, plaintext []byte) ([]byte, error) { | ||||
| 	if s.invalid { | ||||
| 		return nil, ErrCipherSuiteCopied | ||||
| 	} | ||||
| 	if s.n > MaxNonce { | ||||
| 		return nil, ErrMaxNonce | ||||
| 	} | ||||
| 	out = s.c.Encrypt(out, s.n, ad, plaintext) | ||||
| 	s.n++ | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Decrypt checks the authenticity of the ciphertext and authenticated data and | ||||
| // then decrypts and appends the plaintext to out. This method automatically | ||||
| // increments the nonce after every call, messages must be provided in the same | ||||
| // order that they were encrypted with no missing messages. ErrMaxNonce is | ||||
| // returned after the maximum nonce of 2^64-2 is reached. | ||||
| func (s *CipherState) Decrypt(out, ad, ciphertext []byte) ([]byte, error) { | ||||
| 	if s.invalid { | ||||
| 		return nil, ErrCipherSuiteCopied | ||||
| 	} | ||||
| 	if s.n > MaxNonce { | ||||
| 		return nil, ErrMaxNonce | ||||
| 	} | ||||
| 	out, err := s.c.Decrypt(out, s.n, ad, ciphertext) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s.n++ | ||||
| 	return out, nil | ||||
| } | ||||
|  | ||||
| // Cipher returns the low-level symmetric encryption primitive. It should only | ||||
| // be used if nonces need to be managed manually, for example with a network | ||||
| // protocol that can deliver out-of-order messages. This is dangerous, users | ||||
| // must ensure that they are incrementing a nonce after every encrypt operation. | ||||
| // After calling this method, it is an error to call Encrypt/Decrypt on the | ||||
| // CipherState. | ||||
| func (s *CipherState) Cipher() Cipher { | ||||
| 	s.invalid = true | ||||
| 	return s.c | ||||
| } | ||||
|  | ||||
| // Nonce returns the current value of n. This can be used to determine if a | ||||
| // new handshake should be performed due to approaching MaxNonce. | ||||
| func (s *CipherState) Nonce() uint64 { | ||||
| 	return s.n | ||||
| } | ||||
|  | ||||
| func (s *CipherState) Rekey() { | ||||
| 	var zeros [32]byte | ||||
| 	var out []byte | ||||
| 	out = s.c.Encrypt(out, math.MaxUint64, []byte{}, zeros[:]) | ||||
| 	copy(s.k[:], out[:32]) | ||||
| 	s.c = s.cs.Cipher(s.k) | ||||
| } | ||||
|  | ||||
| type symmetricState struct { | ||||
| 	CipherState | ||||
| 	hasK bool | ||||
| 	ck   []byte | ||||
| 	h    []byte | ||||
|  | ||||
| 	prevCK []byte | ||||
| 	prevH  []byte | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) InitializeSymmetric(handshakeName []byte) { | ||||
| 	h := s.cs.Hash() | ||||
| 	if len(handshakeName) <= h.Size() { | ||||
| 		s.h = make([]byte, h.Size()) | ||||
| 		copy(s.h, handshakeName) | ||||
| 	} else { | ||||
| 		h.Write(handshakeName) | ||||
| 		s.h = h.Sum(nil) | ||||
| 	} | ||||
| 	s.ck = make([]byte, len(s.h)) | ||||
| 	copy(s.ck, s.h) | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) MixKey(dhOutput []byte) { | ||||
| 	s.n = 0 | ||||
| 	s.hasK = true | ||||
| 	var hk []byte | ||||
| 	s.ck, hk, _ = hkdf(s.cs.Hash, 2, s.ck[:0], s.k[:0], nil, s.ck, dhOutput) | ||||
| 	copy(s.k[:], hk) | ||||
| 	s.c = s.cs.Cipher(s.k) | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) MixHash(data []byte) { | ||||
| 	h := s.cs.Hash() | ||||
| 	h.Write(s.h) | ||||
| 	h.Write(data) | ||||
| 	s.h = h.Sum(s.h[:0]) | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) MixKeyAndHash(data []byte) { | ||||
| 	var hk []byte | ||||
| 	var temp []byte | ||||
| 	s.ck, temp, hk = hkdf(s.cs.Hash, 3, s.ck[:0], temp, s.k[:0], s.ck, data) | ||||
| 	s.MixHash(temp) | ||||
| 	copy(s.k[:], hk) | ||||
| 	s.c = s.cs.Cipher(s.k) | ||||
| 	s.n = 0 | ||||
| 	s.hasK = true | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) EncryptAndHash(out, plaintext []byte) ([]byte, error) { | ||||
| 	if !s.hasK { | ||||
| 		s.MixHash(plaintext) | ||||
| 		return append(out, plaintext...), nil | ||||
| 	} | ||||
| 	ciphertext, err := s.Encrypt(out, s.h, plaintext) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s.MixHash(ciphertext[len(out):]) | ||||
| 	return ciphertext, nil | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) DecryptAndHash(out, data []byte) ([]byte, error) { | ||||
| 	if !s.hasK { | ||||
| 		s.MixHash(data) | ||||
| 		return append(out, data...), nil | ||||
| 	} | ||||
| 	plaintext, err := s.Decrypt(out, s.h, data) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	s.MixHash(data) | ||||
| 	return plaintext, nil | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) Split() (*CipherState, *CipherState) { | ||||
| 	s1, s2 := &CipherState{cs: s.cs}, &CipherState{cs: s.cs} | ||||
| 	hk1, hk2, _ := hkdf(s.cs.Hash, 2, s1.k[:0], s2.k[:0], nil, s.ck, nil) | ||||
| 	copy(s1.k[:], hk1) | ||||
| 	copy(s2.k[:], hk2) | ||||
| 	s1.c = s.cs.Cipher(s1.k) | ||||
| 	s2.c = s.cs.Cipher(s2.k) | ||||
| 	return s1, s2 | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) Checkpoint() { | ||||
| 	if len(s.ck) > cap(s.prevCK) { | ||||
| 		s.prevCK = make([]byte, len(s.ck)) | ||||
| 	} | ||||
| 	s.prevCK = s.prevCK[:len(s.ck)] | ||||
| 	copy(s.prevCK, s.ck) | ||||
|  | ||||
| 	if len(s.h) > cap(s.prevH) { | ||||
| 		s.prevH = make([]byte, len(s.h)) | ||||
| 	} | ||||
| 	s.prevH = s.prevH[:len(s.h)] | ||||
| 	copy(s.prevH, s.h) | ||||
| } | ||||
|  | ||||
| func (s *symmetricState) Rollback() { | ||||
| 	s.ck = s.ck[:len(s.prevCK)] | ||||
| 	copy(s.ck, s.prevCK) | ||||
| 	s.h = s.h[:len(s.prevH)] | ||||
| 	copy(s.h, s.prevH) | ||||
| } | ||||
|  | ||||
| // A MessagePattern is a single message or operation used in a Noise handshake. | ||||
| type MessagePattern int | ||||
|  | ||||
| // A HandshakePattern is a list of messages and operations that are used to | ||||
| // perform a specific Noise handshake. | ||||
| type HandshakePattern struct { | ||||
| 	Name                 string | ||||
| 	InitiatorPreMessages []MessagePattern | ||||
| 	ResponderPreMessages []MessagePattern | ||||
| 	Messages             [][]MessagePattern | ||||
| } | ||||
|  | ||||
| const ( | ||||
| 	MessagePatternS MessagePattern = iota | ||||
| 	MessagePatternE | ||||
| 	MessagePatternDHEE | ||||
| 	MessagePatternDHES | ||||
| 	MessagePatternDHSE | ||||
| 	MessagePatternDHSS | ||||
| 	MessagePatternPSK | ||||
| ) | ||||
|  | ||||
| // MaxMsgLen is the maximum number of bytes that can be sent in a single Noise | ||||
| // message. | ||||
| const MaxMsgLen = 65535 | ||||
|  | ||||
| // A HandshakeState tracks the state of a Noise handshake. It may be discarded | ||||
| // after the handshake is complete. | ||||
| type HandshakeState struct { | ||||
| 	ss              symmetricState | ||||
| 	s               DHKey  // local static keypair | ||||
| 	e               DHKey  // local ephemeral keypair | ||||
| 	rs              []byte // remote party's static public key | ||||
| 	re              []byte // remote party's ephemeral public key | ||||
| 	psk             []byte // preshared key, maybe zero length | ||||
| 	messagePatterns [][]MessagePattern | ||||
| 	shouldWrite     bool | ||||
| 	initiator       bool | ||||
| 	msgIdx          int | ||||
| 	rng             io.Reader | ||||
| } | ||||
|  | ||||
| // A Config provides the details necessary to process a Noise handshake. It is | ||||
| // never modified by this package, and can be reused. | ||||
| type Config struct { | ||||
| 	// CipherSuite is the set of cryptographic primitives that will be used. | ||||
| 	CipherSuite CipherSuite | ||||
|  | ||||
| 	// Random is the source for cryptographically appropriate random bytes. If | ||||
| 	// zero, it is automatically configured. | ||||
| 	Random io.Reader | ||||
|  | ||||
| 	// Pattern is the pattern for the handshake. | ||||
| 	Pattern HandshakePattern | ||||
|  | ||||
| 	// Initiator must be true if the first message in the handshake will be sent | ||||
| 	// by this peer. | ||||
| 	Initiator bool | ||||
|  | ||||
| 	// Prologue is an optional message that has already be communicated and must | ||||
| 	// be identical on both sides for the handshake to succeed. | ||||
| 	Prologue []byte | ||||
|  | ||||
| 	// PresharedKey is the optional preshared key for the handshake. | ||||
| 	PresharedKey []byte | ||||
|  | ||||
| 	// PresharedKeyPlacement specifies the placement position of the PSK token | ||||
| 	// when PresharedKey is specified | ||||
| 	PresharedKeyPlacement int | ||||
|  | ||||
| 	// StaticKeypair is this peer's static keypair, required if part of the | ||||
| 	// handshake. | ||||
| 	StaticKeypair DHKey | ||||
|  | ||||
| 	// EphemeralKeypair is this peer's ephemeral keypair that was provided as | ||||
| 	// a pre-message in the handshake. | ||||
| 	EphemeralKeypair DHKey | ||||
|  | ||||
| 	// PeerStatic is the static public key of the remote peer that was provided | ||||
| 	// as a pre-message in the handshake. | ||||
| 	PeerStatic []byte | ||||
|  | ||||
| 	// PeerEphemeral is the ephemeral public key of the remote peer that was | ||||
| 	// provided as a pre-message in the handshake. | ||||
| 	PeerEphemeral []byte | ||||
| } | ||||
|  | ||||
| // NewHandshakeState starts a new handshake using the provided configuration. | ||||
| func NewHandshakeState(c Config) (*HandshakeState, error) { | ||||
| 	hs := &HandshakeState{ | ||||
| 		s:               c.StaticKeypair, | ||||
| 		e:               c.EphemeralKeypair, | ||||
| 		rs:              c.PeerStatic, | ||||
| 		psk:             c.PresharedKey, | ||||
| 		messagePatterns: c.Pattern.Messages, | ||||
| 		shouldWrite:     c.Initiator, | ||||
| 		initiator:       c.Initiator, | ||||
| 		rng:             c.Random, | ||||
| 	} | ||||
| 	if hs.rng == nil { | ||||
| 		hs.rng = rand.Reader | ||||
| 	} | ||||
| 	if len(c.PeerEphemeral) > 0 { | ||||
| 		hs.re = make([]byte, len(c.PeerEphemeral)) | ||||
| 		copy(hs.re, c.PeerEphemeral) | ||||
| 	} | ||||
| 	hs.ss.cs = c.CipherSuite | ||||
| 	pskModifier := "" | ||||
| 	if len(hs.psk) > 0 { | ||||
| 		if len(hs.psk) != 32 { | ||||
| 			return nil, errors.New("noise: specification mandates 256-bit preshared keys") | ||||
| 		} | ||||
| 		pskModifier = fmt.Sprintf("psk%d", c.PresharedKeyPlacement) | ||||
| 		hs.messagePatterns = append([][]MessagePattern(nil), hs.messagePatterns...) | ||||
| 		if c.PresharedKeyPlacement == 0 { | ||||
| 			hs.messagePatterns[0] = append([]MessagePattern{MessagePatternPSK}, hs.messagePatterns[0]...) | ||||
| 		} else { | ||||
| 			hs.messagePatterns[c.PresharedKeyPlacement-1] = append(hs.messagePatterns[c.PresharedKeyPlacement-1], MessagePatternPSK) | ||||
| 		} | ||||
| 	} | ||||
| 	hs.ss.InitializeSymmetric([]byte("Noise_" + c.Pattern.Name + pskModifier + "_" + string(hs.ss.cs.Name()))) | ||||
| 	hs.ss.MixHash(c.Prologue) | ||||
| 	for _, m := range c.Pattern.InitiatorPreMessages { | ||||
| 		switch { | ||||
| 		case c.Initiator && m == MessagePatternS: | ||||
| 			hs.ss.MixHash(hs.s.Public) | ||||
| 		case c.Initiator && m == MessagePatternE: | ||||
| 			hs.ss.MixHash(hs.e.Public) | ||||
| 		case !c.Initiator && m == MessagePatternS: | ||||
| 			hs.ss.MixHash(hs.rs) | ||||
| 		case !c.Initiator && m == MessagePatternE: | ||||
| 			hs.ss.MixHash(hs.re) | ||||
| 		} | ||||
| 	} | ||||
| 	for _, m := range c.Pattern.ResponderPreMessages { | ||||
| 		switch { | ||||
| 		case !c.Initiator && m == MessagePatternS: | ||||
| 			hs.ss.MixHash(hs.s.Public) | ||||
| 		case !c.Initiator && m == MessagePatternE: | ||||
| 			hs.ss.MixHash(hs.e.Public) | ||||
| 		case c.Initiator && m == MessagePatternS: | ||||
| 			hs.ss.MixHash(hs.rs) | ||||
| 		case c.Initiator && m == MessagePatternE: | ||||
| 			hs.ss.MixHash(hs.re) | ||||
| 		} | ||||
| 	} | ||||
| 	return hs, nil | ||||
| } | ||||
|  | ||||
| // WriteMessage appends a handshake message to out. The message will include the | ||||
| // optional payload if provided. If the handshake is completed by the call, two | ||||
| // CipherStates will be returned, one is used for encryption of messages to the | ||||
| // remote peer, the other is used for decryption of messages from the remote | ||||
| // peer. It is an error to call this method out of sync with the handshake | ||||
| // pattern. | ||||
| func (s *HandshakeState) WriteMessage(out, payload []byte) ([]byte, *CipherState, *CipherState, error) { | ||||
| 	if !s.shouldWrite { | ||||
| 		return nil, nil, nil, errors.New("noise: unexpected call to WriteMessage should be ReadMessage") | ||||
| 	} | ||||
| 	if s.msgIdx > len(s.messagePatterns)-1 { | ||||
| 		return nil, nil, nil, errors.New("noise: no handshake messages left") | ||||
| 	} | ||||
| 	if len(payload) > MaxMsgLen { | ||||
| 		return nil, nil, nil, errors.New("noise: message is too long") | ||||
| 	} | ||||
|  | ||||
| 	var err error | ||||
| 	for _, msg := range s.messagePatterns[s.msgIdx] { | ||||
| 		switch msg { | ||||
| 		case MessagePatternE: | ||||
| 			e, err := s.ss.cs.GenerateKeypair(s.rng) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			s.e = e | ||||
| 			out = append(out, s.e.Public...) | ||||
| 			s.ss.MixHash(s.e.Public) | ||||
| 			if len(s.psk) > 0 { | ||||
| 				s.ss.MixKey(s.e.Public) | ||||
| 			} | ||||
| 		case MessagePatternS: | ||||
| 			if len(s.s.Public) == 0 { | ||||
| 				return nil, nil, nil, errors.New("noise: invalid state, s.Public is nil") | ||||
| 			} | ||||
| 			out, err = s.ss.EncryptAndHash(out, s.s.Public) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 		case MessagePatternDHEE: | ||||
| 			dh, err := s.ss.cs.DH(s.e.Private, s.re) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			s.ss.MixKey(dh) | ||||
| 		case MessagePatternDHES: | ||||
| 			if s.initiator { | ||||
| 				dh, err := s.ss.cs.DH(s.e.Private, s.rs) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} else { | ||||
| 				dh, err := s.ss.cs.DH(s.s.Private, s.re) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} | ||||
| 		case MessagePatternDHSE: | ||||
| 			if s.initiator { | ||||
| 				dh, err := s.ss.cs.DH(s.s.Private, s.re) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} else { | ||||
| 				dh, err := s.ss.cs.DH(s.e.Private, s.rs) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} | ||||
| 		case MessagePatternDHSS: | ||||
| 			dh, err := s.ss.cs.DH(s.s.Private, s.rs) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			s.ss.MixKey(dh) | ||||
| 		case MessagePatternPSK: | ||||
| 			s.ss.MixKeyAndHash(s.psk) | ||||
| 		} | ||||
| 	} | ||||
| 	s.shouldWrite = false | ||||
| 	s.msgIdx++ | ||||
| 	out, err = s.ss.EncryptAndHash(out, payload) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, nil, err | ||||
| 	} | ||||
|  | ||||
| 	if s.msgIdx >= len(s.messagePatterns) { | ||||
| 		cs1, cs2 := s.ss.Split() | ||||
| 		return out, cs1, cs2, nil | ||||
| 	} | ||||
|  | ||||
| 	return out, nil, nil, nil | ||||
| } | ||||
|  | ||||
| // ErrShortMessage is returned by ReadMessage if a message is not as long as it should be. | ||||
| var ErrShortMessage = errors.New("noise: message is too short") | ||||
|  | ||||
| // ReadMessage processes a received handshake message and appends the payload, | ||||
| // if any to out. If the handshake is completed by the call, two CipherStates | ||||
| // will be returned, one is used for encryption of messages to the remote peer, | ||||
| // the other is used for decryption of messages from the remote peer. It is an | ||||
| // error to call this method out of sync with the handshake pattern. | ||||
| func (s *HandshakeState) ReadMessage(out, message []byte) ([]byte, *CipherState, *CipherState, error) { | ||||
| 	if s.shouldWrite { | ||||
| 		return nil, nil, nil, errors.New("noise: unexpected call to ReadMessage should be WriteMessage") | ||||
| 	} | ||||
| 	if s.msgIdx > len(s.messagePatterns)-1 { | ||||
| 		return nil, nil, nil, errors.New("noise: no handshake messages left") | ||||
| 	} | ||||
|  | ||||
| 	rsSet := false | ||||
| 	s.ss.Checkpoint() | ||||
|  | ||||
| 	var err error | ||||
| 	for _, msg := range s.messagePatterns[s.msgIdx] { | ||||
| 		switch msg { | ||||
| 		case MessagePatternE, MessagePatternS: | ||||
| 			expected := s.ss.cs.DHLen() | ||||
| 			if msg == MessagePatternS && s.ss.hasK { | ||||
| 				expected += 16 | ||||
| 			} | ||||
| 			if len(message) < expected { | ||||
| 				return nil, nil, nil, ErrShortMessage | ||||
| 			} | ||||
| 			switch msg { | ||||
| 			case MessagePatternE: | ||||
| 				if cap(s.re) < s.ss.cs.DHLen() { | ||||
| 					s.re = make([]byte, s.ss.cs.DHLen()) | ||||
| 				} | ||||
| 				s.re = s.re[:s.ss.cs.DHLen()] | ||||
| 				copy(s.re, message) | ||||
| 				s.ss.MixHash(s.re) | ||||
| 				if len(s.psk) > 0 { | ||||
| 					s.ss.MixKey(s.re) | ||||
| 				} | ||||
| 			case MessagePatternS: | ||||
| 				if len(s.rs) > 0 { | ||||
| 					return nil, nil, nil, errors.New("noise: invalid state, rs is not nil") | ||||
| 				} | ||||
| 				s.rs, err = s.ss.DecryptAndHash(s.rs[:0], message[:expected]) | ||||
| 				rsSet = true | ||||
| 			} | ||||
| 			if err != nil { | ||||
| 				s.ss.Rollback() | ||||
| 				if rsSet { | ||||
| 					s.rs = nil | ||||
| 				} | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			message = message[expected:] | ||||
| 		case MessagePatternDHEE: | ||||
| 			dh, err := s.ss.cs.DH(s.e.Private, s.re) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			s.ss.MixKey(dh) | ||||
| 		case MessagePatternDHES: | ||||
| 			if s.initiator { | ||||
| 				dh, err := s.ss.cs.DH(s.e.Private, s.rs) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} else { | ||||
| 				dh, err := s.ss.cs.DH(s.s.Private, s.re) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} | ||||
| 		case MessagePatternDHSE: | ||||
| 			if s.initiator { | ||||
| 				dh, err := s.ss.cs.DH(s.s.Private, s.re) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} else { | ||||
| 				dh, err := s.ss.cs.DH(s.e.Private, s.rs) | ||||
| 				if err != nil { | ||||
| 					return nil, nil, nil, err | ||||
| 				} | ||||
| 				s.ss.MixKey(dh) | ||||
| 			} | ||||
| 		case MessagePatternDHSS: | ||||
| 			dh, err := s.ss.cs.DH(s.s.Private, s.rs) | ||||
| 			if err != nil { | ||||
| 				return nil, nil, nil, err | ||||
| 			} | ||||
| 			s.ss.MixKey(dh) | ||||
| 		case MessagePatternPSK: | ||||
| 			s.ss.MixKeyAndHash(s.psk) | ||||
| 		} | ||||
| 	} | ||||
| 	out, err = s.ss.DecryptAndHash(out, message) | ||||
| 	if err != nil { | ||||
| 		s.ss.Rollback() | ||||
| 		if rsSet { | ||||
| 			s.rs = nil | ||||
| 		} | ||||
| 		return nil, nil, nil, err | ||||
| 	} | ||||
| 	s.shouldWrite = true | ||||
| 	s.msgIdx++ | ||||
|  | ||||
| 	if s.msgIdx >= len(s.messagePatterns) { | ||||
| 		cs1, cs2 := s.ss.Split() | ||||
| 		return out, cs1, cs2, nil | ||||
| 	} | ||||
|  | ||||
| 	return out, nil, nil, nil | ||||
| } | ||||
|  | ||||
| // ChannelBinding provides a value that uniquely identifies the session and can | ||||
| // be used as a channel binding. It is an error to call this method before the | ||||
| // handshake is complete. | ||||
| func (s *HandshakeState) ChannelBinding() []byte { | ||||
| 	return s.ss.h | ||||
| } | ||||
|  | ||||
| // PeerStatic returns the static key provided by the remote peer during | ||||
| // a handshake. It is an error to call this method if a handshake message | ||||
| // containing a static key has not been read. | ||||
| func (s *HandshakeState) PeerStatic() []byte { | ||||
| 	return s.rs | ||||
| } | ||||
|  | ||||
| // MessageIndex returns the current handshake message id | ||||
| func (s *HandshakeState) MessageIndex() int { | ||||
| 	return s.msgIdx | ||||
| } | ||||
|  | ||||
| // PeerEphemeral returns the ephemeral key provided by the remote peer during | ||||
| // a handshake. It is an error to call this method if a handshake message | ||||
| // containing a static key has not been read. | ||||
| func (s *HandshakeState) PeerEphemeral() []byte { | ||||
| 	return s.re | ||||
| } | ||||
|  | ||||
| // LocalEphemeral returns the local ephemeral key pair generated during | ||||
| // a handshake. | ||||
| func (s *HandshakeState) LocalEphemeral() DHKey { | ||||
| 	return s.e | ||||
| } | ||||
							
								
								
									
										28640
									
								
								vendor/github.com/flynn/noise/vectors.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28640
									
								
								vendor/github.com/flynn/noise/vectors.txt
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user
	 anthonyrawlins
					anthonyrawlins