/// <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"); } }
/// <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"); } }
/// <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; }