/// <summary>
        /// Updates the <see cref="Crypto8"/> with the other end's public key according to the <see cref="MessageDirection"/>
        /// the <see cref="Crypto8"/> was initialized with.
        /// </summary>
        /// <remarks>
        /// The Blake2B nonce will be generated depending on the state of the <see cref="Crypto8"/>.
        /// </remarks>
        /// <param name="publicKey">Other end's public key.</param>
        /// <exception cref="ArgumentNullException"><paramref name="publicKey"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="publicKey"/> length is not 32.</exception>
        public void UpdateSharedKey(byte[] publicKey)
        {
            if (publicKey == null)
            {
                throw new ArgumentNullException(nameof(publicKey));
            }
            if (publicKey.Length != PublicKeyBox.PublicKeyLength)
            {
                throw new ArgumentOutOfRangeException(nameof(publicKey), "Key must be 32 bytes in length.");
            }

            if (_cryptoState == CryptoState.SecoundKey)
            {
                throw new InvalidOperationException("Cannot update 'k' because it has already been set.");
            }
            else if (_cryptoState == CryptoState.None)
            {
                // Order of keys is important.
                // We're the server.
                if (Direction == MessageDirection.Client)
                {
                    _blake2bNonce = GenerateBlake2BNonce(publicKey, _keyPair.PublicKey);
                }
                // We're the client.
                else
                {
                    _blake2bNonce = GenerateBlake2BNonce(_keyPair.PublicKey, publicKey);
                }

                // We got initial key and Blake nonce.
                _cryptoState = CryptoState.InitialKey;
            }
            else
            {
                // Make sure we have a decrypt nonce before decrypting with k.
                if (_decryptNonce == null)
                {
                    throw new InvalidOperationException("Cannot update shared key 'k' because did not provide a decrypt nonce.");
                }

                // Make sure we have an encrypt nonce before encrypting with k
                if (_encryptNonce == null)
                {
                    throw new InvalidOperationException("Cannot update shared key 'k' because did not provide an encrypt nonce.");
                }

                _cryptoState = CryptoState.SecoundKey;
            }

            _sharedKey = publicKey;
        }
        /// <summary>
        /// Updates the specified <see cref="UpdateNonceType"/> with the specified nonce.
        /// </summary>
        /// <param name="nonce">Nonce to use for the update.</param>
        /// <param name="nonceType">Nonce type to update.</param>
        /// <exception cref="ArgumentNullException"><paramref name="nonce"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="nonce"/> length is not 24.</exception>
        public void UpdateNonce(byte[] nonce, UpdateNonceType nonceType)
        {
            if (_cryptoState == CryptoState.SecoundKey)
            {
                throw new InvalidOperationException("Cannot update nonce after updated with shared key 'k'.");
            }
            if (nonce == null)
            {
                throw new ArgumentNullException(nameof(nonce));
            }
            if (nonce.Length != 24)
            {
                throw new ArgumentOutOfRangeException(nameof(nonce), "nonce must be 24 bytes in length.");
            }

            switch (nonceType)
            {
            case UpdateNonceType.Blake:
                if (_cryptoState == CryptoState.InitialKey)
                {
                    if (Direction == MessageDirection.Client)     // order of keys is important. we're the server
                    {
                        _blake2bNonce = GenerateBlake2BNonce(nonce, _sharedKey, _keyPair.PublicKey);
                    }
                    else     // we're the client
                    {
                        _blake2bNonce = GenerateBlake2BNonce(nonce, _keyPair.PublicKey, _sharedKey);
                    }

                    _cryptoState = CryptoState.BlakeNonce;     // use blake nonce
                }
                break;

            case UpdateNonceType.Decrypt:
                _decryptNonce = nonce;
                break;

            case UpdateNonceType.Encrypt:
                _encryptNonce = nonce;
                break;

            default:
                throw new ArgumentException("Unexpected NonceType: " + nonceType, "nonceType");
            }
        }
示例#3
0
        /// <summary>
        /// Updates the specified <see cref="UpdateNonceType"/> with the specified nonce.
        /// </summary>
        /// <param name="nonce">Nonce to use for the update.</param>
        /// <param name="nonceType">Nonce type to update.</param>
        /// <exception cref="ArgumentNullException"><paramref name="nonce"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="nonce"/> length is not 24.</exception>
        public void UpdateNonce(byte[] nonce, UpdateNonceType nonceType)
        {
            if (_cryptoState == CryptoState.SecoundKey) // can only be updated twice
                throw new InvalidOperationException("Cannot update nonce after updated with shared key 'k'.");
            if (nonce == null)
                throw new ArgumentNullException("nonce");
            if (nonce.Length != CoCKeyPair.NonceLength)
                throw new ArgumentOutOfRangeException("nonce", "nonce must be 24 bytes in length.");

            switch (nonceType)
            {
                case UpdateNonceType.Blake:
                    if (_cryptoState == CryptoState.InitialKey)
                    {
                        if (Direction == MessageDirection.Client) // order of keys is important. we're the server
                            _blake2bNonce = GenerateBlake2BNonce(nonce, _sharedKey, _keyPair.PublicKey);
                        else // we're the client
                            _blake2bNonce = GenerateBlake2BNonce(nonce, _keyPair.PublicKey, _sharedKey);

                        _cryptoState = CryptoState.BlakeNonce; // use blake nonce
                    }
                    break;

                case UpdateNonceType.Decrypt:
                    _decryptNonce = nonce;
                    break;

                case UpdateNonceType.Encrypt:
                    _encryptNonce = nonce;
                    break;

                default:
                    throw new ArgumentException("Unexpected NonceType: " + nonceType, "nonceType");
            }
        }
示例#4
0
        /// <summary>
        /// Updates the <see cref="Crypto8"/> with the other end's public key according to the
        /// <see cref="MessageDirection"/> the <see cref="Crypto8"/> was initialized with.
        /// </summary>
        /// <remarks>
        /// The blake2b nonce will be generated as well.
        /// </remarks>
        /// <param name="publicKey">Other end's public key.</param>
        /// <exception cref="ArgumentNullException"><paramref name="publicKey"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="publicKey"/> length is not 32.</exception>
        public void UpdateSharedKey(byte[] publicKey)
        {
            if (publicKey == null)
                throw new ArgumentNullException("publicKey");
            if (publicKey.Length != CoCKeyPair.KeyLength)
                throw new ArgumentOutOfRangeException("publicKey", "publicKey must be 32 bytes in length.");

            if (_cryptoState == CryptoState.SecoundKey)
                throw new InvalidOperationException();
            else if (_cryptoState == CryptoState.None)
            {
                if (Direction == MessageDirection.Client) // order of keys is important. we're the server
                    _blake2bNonce = GenerateBlake2BNonce(publicKey, _keyPair.PublicKey);
                else // we're the client
                    _blake2bNonce = GenerateBlake2BNonce(_keyPair.PublicKey, publicKey);

                _cryptoState = CryptoState.InitialKey; // we got initial key and blakenonce
            }
            else
            {
                if (_decryptNonce == null) // make sure we have a decrypt nonce before decrypting with k
                    throw new InvalidOperationException("Cannot update shared key 'k' because did not provide a decrypt nonce.");

                if (_encryptNonce == null) // make sure we have an encrypt nonce before encrypting with k
                    throw new InvalidOperationException("Cannot update shared key 'k' because did not provide a encrypt nonce.");

                _cryptoState = CryptoState.SecoundKey;
            }

            _sharedKey = publicKey;
        }