Exemple #1
0
        /// <summary>
        /// Transcript-Hash(M1, M2, ... Mn) = Hash(M1 || M2 || ... || Mn)
        /// </summary>
        /// <param name="messages"></param>
        /// <returns></returns>
        public BitString TranscriptHash(params BitString[] messages)
        {
            var concatenatedMessages = BitString.Empty();

            foreach (var message in messages)
            {
                concatenatedMessages = concatenatedMessages.ConcatenateBits(message);
            }

            return(_sha.HashMessage(concatenatedMessages).Digest);
        }
Exemple #2
0
        public TlsKdfV13HandshakeSecretResult GetDerivedHandshakeSecret(BitString diffieHellmanSharedSecret, BitString salt,
                                                                        BitString clientHello, BitString serverHello)
        {
            var handshakeSecret = _hkdf.Extract(salt, diffieHellmanSharedSecret);

            var clientHandshakeTrafficSecret = DeriveSecret(handshakeSecret, "c hs traffic", clientHello, serverHello);
            var serverHandshakeTrafficSecret = DeriveSecret(handshakeSecret, "s hs traffic", clientHello, serverHello);

            var derivedHandshakeSecret = DeriveSecret(handshakeSecret, "derived", BitString.Empty());

            return(new TlsKdfV13HandshakeSecretResult()
            {
                HandshakeSecret = handshakeSecret,
                ClientHandshakeTrafficSecret = clientHandshakeTrafficSecret,
                ServerHandshakeTrafficSecret = serverHandshakeTrafficSecret,
                DerivedHandshakeSecret = derivedHandshakeSecret,
            });
        }
Exemple #3
0
        public TlsKdfV13EarlySecretResult GetDerivedEarlySecret(bool isExternalPsk, BitString preSharedKey, BitString clientHello)
        {
            var earlySecret = _hkdf.Extract(_bitstringHashLengthBits, preSharedKey);

            var binderKey = DeriveSecret(earlySecret, isExternalPsk ? "ext binder" : "res binder", BitString.Empty());
            var clientEarlyTrafficSecret  = DeriveSecret(earlySecret, "c e traffic", clientHello);
            var earlyExporterMasterSecret = DeriveSecret(earlySecret, "e exp master", clientHello);

            var derivedEarlySecret = DeriveSecret(earlySecret, "derived", BitString.Empty());

            return(new TlsKdfV13EarlySecretResult()
            {
                EarlySecret = earlySecret,
                BinderKey = binderKey,
                ClientEarlyTrafficSecret = clientEarlyTrafficSecret,
                EarlyExporterMasterSecret = earlyExporterMasterSecret,
                DerivedEarlySecret = derivedEarlySecret,
            });
        }
Exemple #4
0
        /// <summary>
        /// HKDF-Expand-Label(Secret, Label, Context, Length) =
        ///   HKDF-Expand(Secret, HkdfLabel, Length)
        ///
        /// The Hash function used by Transcript-Hash and HKDF is the cipher
        ///    suite hash algorithm.  Hash.length is its output length in bytes.
        ///    Messages is the concatenation of the indicated handshake messages,
        ///    including the handshake message type and length fields, but not
        ///    including record layer headers.  Note that in some cases a zero-
        ///    length Context (indicated by "") is passed to HKDF-Expand-Label.  The
        ///    labels specified in this document are all ASCII strings and do not
        ///    include a trailing NUL byte.
        /// </summary>
        /// <param name="secret">The secret.</param>
        /// <param name="label">The label of the intermediate value.</param>
        /// <param name="context">The context of the KDF step.</param>
        /// <param name="hashLengthBytes">Hash output length in bytes.</param>
        /// <returns>HKDF expanded bitstring based on the secret and built other info.</returns>
        public BitString ExpandLabel(BitString secret, string label, BitString context, int hashLengthBytes)
        {
            const int maxLabelContextSizes = 255;
            var       expandedLabel        = Encoding.ASCII.GetBytes("tls13 " + label);

            if (label.Length > maxLabelContextSizes)
            {
                throw new ArgumentOutOfRangeException($"{nameof(label)} exceeds max labels length of {maxLabelContextSizes}");
            }

            if (context.BitLength.CeilingDivide(maxLabelContextSizes) > maxLabelContextSizes)
            {
                throw new ArgumentOutOfRangeException($"{nameof(context)} exceeds max labels length of {maxLabelContextSizes}");
            }

            var otherInfo = BitString.Empty()
                            .ConcatenateBits(BitString.To16BitString((short)hashLengthBytes))
                            .ConcatenateBits(BitString.To8BitString((byte)expandedLabel.Length))
                            .ConcatenateBits(new BitString(expandedLabel))
                            .ConcatenateBits(BitString.To8BitString((byte)(context.BitLength / BitString.BITSINBYTE)))
                            .ConcatenateBits(context);

            return(_hkdf.Expand(secret, otherInfo, hashLengthBytes));
        }