/// <summary> /// Initializes a new instance of the <see cref="Protocol"/> class. /// </summary> /// <param name="handshakePattern">The handshake pattern (e.q. NX or IK).</param> /// <param name="cipher">The cipher function (AESGCM or ChaChaPoly).</param> /// <param name="hash">The hash function (SHA256, SHA512, BLAKE2s, or BLAKE2b).</param> /// <param name="modifiers">The combination of pattern modifiers (e.q. empty, psk0, or psk1+psk2).</param> /// <exception cref="ArgumentNullException"> /// Thrown if the either <paramref name="handshakePattern"/>, /// <paramref name="cipher"/>, or <paramref name="hash"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="modifiers"/> does not represent a valid combination of pattern modifiers. /// </exception> public Protocol( HandshakePattern handshakePattern, CipherFunction cipher, HashFunction hash, PatternModifiers modifiers = PatternModifiers.None) { Exceptions.ThrowIfNull(handshakePattern, nameof(handshakePattern)); Exceptions.ThrowIfNull(cipher, nameof(cipher)); Exceptions.ThrowIfNull(hash, nameof(hash)); HandshakePattern = handshakePattern; Cipher = cipher; Dh = DhFunction.Curve25519; Hash = hash; Modifiers = modifiers; Name = GetName(); }
/// <summary> /// Converts the Noise protocol name to its <see cref="Protocol"/> equivalent. /// </summary> /// <param name="s">The Noise protocol name (e.q. Noise_KNpsk2_25519_ChaChaPoly_SHA512).</param> /// <returns> /// An object that is equivalent to the Noise /// protocol name contained in <paramref name="s"/>. /// </returns> /// <exception cref="ArgumentException"> /// Thrown if <paramref name="s"/> is not a valid Noise protocol name. /// </exception> public static Protocol Parse(ReadOnlySpan <char> s) { if (s.Length < MinProtocolNameLength || s.Length > MaxProtocolNameLength) { throw new ArgumentException("Invalid Noise protocol name.", nameof(s)); } var splitter = new StringSplitter(s, '_'); var noise = splitter.Next(); if (!noise.SequenceEqual("Noise".AsSpan())) { throw new ArgumentException("Invalid Noise protocol name.", nameof(s)); } var next = splitter.Next(); var pattern = next.Length > 1 && Char.IsUpper(next[1]) ? next.Slice(0, 2) : next.Slice(0, 1); var handshakePattern = ParseHandshakePattern(pattern); var modifiers = ParseModifiers(next.Slice(pattern.Length)); var dh = DhFunction.Parse(splitter.Next()); Debug.Assert(dh == DhFunction.Curve25519); var cipher = CipherFunction.Parse(splitter.Next()); var hash = HashFunction.Parse(splitter.Next()); if (!splitter.Next().IsEmpty) { throw new ArgumentException("Invalid Noise protocol name.", nameof(s)); } var protocol = new Protocol(handshakePattern, cipher, hash, modifiers); ValidateProtocolName(s, protocol); return(protocol); }