コード例 #1
0
        /// <summary>
        /// initial netlogon signature token when AES is not negotiated
        /// </summary>
        /// <param name="sequenceNumber">sequence number</param>
        /// <param name="sessionKey">session key</param>
        /// <param name="requestConfidentiality">confidentiality is required or not</param>
        /// <param name="isClientSideOutbound">Is client side outbound message.</param>
        /// <param name="securityBuffers">
        /// Security buffers, contains input plain-text; output cipher-text and signature.
        /// </param>
        private static void InitialNetlogonSignatureTokenWhenAesIsNotNegotiated(
            ref ulong sequenceNumber,
            byte[] sessionKey,
            bool requestConfidentiality,
            bool isClientSideOutbound,
            SecurityBuffer[] securityBuffers)
        {
            byte[] plainText;
            byte[] cipherText;
            byte[] token;
            NL_AUTH_SIGNATURE nlAuthSign = new NL_AUTH_SIGNATURE();

            //The SignatureAlgorithm first byte MUST be set to 0x77
            //and the second byte MUST be set to 0x00.
            nlAuthSign.SignatureAlgorithm = SignatureAlgorithm_Values.HMACMD5;

            if (requestConfidentiality)
            {
                //If the Confidentiality option (section 3.3.1) is requested
                //from the application, then the SealAlgorithm first byte MUST
                //be set to 0x7A, the second byte MUST be set to 0x00, and
                //the Confounder MUST be filled with cryptographically random data.
                nlAuthSign.SealAlgorithm = SealAlgorithm_Values.RC4;
                nlAuthSign.Confounder = GenerateNonce(NL_AUTH_SIGNATURE_CONFOUNDER_LENGTH);
            }
            else
            {
                //If the Confidentiality option is not requested, then the
                //SealAlgorithm MUST be filled with two bytes of value 0xff,
                //and the Confounder is not included in the token.
                nlAuthSign.SealAlgorithm = SealAlgorithm_Values.NotEncrypted;
                nlAuthSign.Confounder = null;
            }

            //The Pad MUST be filled with 0xff bytes.
            nlAuthSign.Pad = Pad_Values.V1;

            //The Flags MUST be filled with 0x00 bytes.
            nlAuthSign.Flags = new byte[NL_AUTH_SIGNATURE_FLAGS_LENGTH];

            //The SequenceNumber MUST be computed using the following algorithm.
            nlAuthSign.SequenceNumber = ComputeCopySequenceNumber(sequenceNumber, isClientSideOutbound);

            //The ClientSequenceNumber MUST be incremented by 1.
            sequenceNumber += 1;

            //Compute signature
            plainText = ConcatenateSecurityBuffersForChecksum(securityBuffers);
            nlAuthSign.Checksum = ComputeSignatureWhenAesIsNotNegotiated(
                nlAuthSign,
                sessionKey,
                requestConfidentiality,
                plainText);

            //If the Confidentiality option is requested, the data and the Confounder
            //field MUST be encrypted. If AES is not negotiated, it MUST use the
            //RC4 algorithm.
            if (requestConfidentiality)
            {
                byte[] rc4EncryptionKey = ComputeEncryptionKeyWhenAesIsNotNegotiated(
                    sessionKey,
                    nlAuthSign.SequenceNumber);

                using (RC4 rc4 = RC4.Create())
                {
                    rc4.Key = rc4EncryptionKey;
                    nlAuthSign.Confounder = rc4.CreateEncryptor().TransformFinalBlock(
                        nlAuthSign.Confounder,
                        0,
                        nlAuthSign.Confounder.Length);

                    plainText = SspiUtility.ConcatenateReadWriteSecurityBuffers(
                        securityBuffers,
                        SecurityBufferType.Data);
                    cipherText = rc4.CreateEncryptor().TransformFinalBlock(
                        plainText,
                        0,
                        plainText.Length);
                }

                SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data, cipherText);
            }
            else
            {
                cipherText = null;
            }

            //The SequenceNumber MUST be encrypted.
            //If AES is not negotiated, it MUST use the RC4 algorithm.
            //The RC4 key MUST be derived as follows:
            //SET zeroes to 4 bytes of 0
            //CALL hmac_md5(zeroes, [4 bytes], SessionKey, size of SessionKey, TmpData)
            //CALL hmac_md5(Checksum, size of Checksum, TmpData, size of TmpData, EncryptionKey)
            byte[] tmpData;
            byte[] sequenceNumberEncryptionKey;
            using (HMACMD5 hmacMd5 = new HMACMD5(sessionKey))
            {
                tmpData = hmacMd5.ComputeHash(new byte[4]);
            }
            using (HMACMD5 hmacMd5 = new HMACMD5(tmpData))
            {
                sequenceNumberEncryptionKey = hmacMd5.ComputeHash(nlAuthSign.Checksum);
            }
            using (RC4 rc4 = RC4.Create())
            {
                rc4.Key = sequenceNumberEncryptionKey;
                nlAuthSign.SequenceNumber = rc4.CreateEncryptor().TransformFinalBlock(
                    nlAuthSign.SequenceNumber,
                    0,
                    nlAuthSign.SequenceNumber.Length);
            }

            token = TypeMarshal.ToBytes(nlAuthSign);
            SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, token);
        }
コード例 #2
0
        /// <summary>
        /// Compute signature when AES is not negotiated
        /// </summary>
        /// <param name="nlAuthSign">NL_AUTH_SIGNATURE struct</param>
        /// <param name="sessionKey">session key</param>
        /// <param name="requestConfidentiality">confidentiality is required or not</param>
        /// <param name="plainText">plain-text message to make signature</param>
        /// <returns>signature</returns>
        private static byte[] ComputeSignatureWhenAesIsNotNegotiated(
            NL_AUTH_SIGNATURE nlAuthSign,
            byte[] sessionKey,
            bool requestConfidentiality,
            byte[] plainText)
        {
            //If AES is not negotiated, a signature MUST be computed using
            //the following algorithm:
            //SET zeroes to 4 bytes of 0
            //CALL MD5Init(md5context)
            //CALL MD5Update(md5context, zeroes, [4 bytes])
            //CALL MD5Update(md5context, NL_AUTH_SIGNATURE, [8 bytes])
            //IF Confidentiality requested
            //CALL MD5Update(md5context, Confounder, [8 bytes])
            //CALL MD5Update(md5context, Message, size of Message)
            //CALL MD5Final(md5context)
            //CALL HMAC_MD5(md5context.digest, md5context.digest length,
            //Session-Key, size of Session Key, output)
            //SET Signature to output
            //Note: In the second call to MD5Update, only the first 8-bytes
            //of the NL_AUTH_SIGNATURE structure are used.
            byte[] signature;

            byte[] buf = ArrayUtility.ConcatenateArrays(
                new byte[4],
                BitConverter.GetBytes((ushort)nlAuthSign.SignatureAlgorithm),
                BitConverter.GetBytes((ushort)nlAuthSign.SealAlgorithm),
                BitConverter.GetBytes((ushort)nlAuthSign.Pad),
                nlAuthSign.Flags);

            if (requestConfidentiality)
            {
                buf = ArrayUtility.ConcatenateArrays(
                    buf,
                    nlAuthSign.Confounder);
            }

            buf = ArrayUtility.ConcatenateArrays(
                buf,
                plainText);

            using (MD5 md5 = MD5.Create())
            {
                signature = md5.ComputeHash(buf);
            }
            using (HMACMD5 hmacMd5 = new HMACMD5(sessionKey))
            {
                signature = hmacMd5.ComputeHash(signature);
            }

            //After the signature is computed, the signature MUST be truncated,
            //with only the first 8 bytes being copied into the Checksum field
            //of NL_AUTH_SIGNATURE.
            signature = ArrayUtility.SubArray(signature, 0, NL_AUTH_SIGNATURE_CHECKSUM_LENGTH);

            return signature;
        }