/// <summary> /// Verify a request or response /// </summary> /// <param name="securityBuffers">Security buffers containing encrypted data.</param> /// <param name="sentFromClient">True if the token is a request, false is a response</param> /// <returns>True if verify succeed; otherwise, false.</returns> private bool Verify(SecurityBuffer[] securityBuffers, bool sentFromClient) { KileContext context = sentFromClient ? (KileContext)kileDecoder.serverContext : (KileContext)kileDecoder.clientContext; KilePdu pdu; return(KileRole.GssVerifyMicEx(context, securityBuffers, out pdu)); }
/// <summary> /// Encrypts Message. User decides what SecBuffers are used. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to encrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static void Encrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { byte[] message = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data); byte[] token = SspiUtility.ConcatenateSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (token.Length == 0) { throw new ArgumentException("Token buffer is not valid."); } SGN_ALG sgnAlg = GetSgnAlg(kileRole); KilePdu pdu = kileRole.GssWrap(true, sgnAlg, message); byte[] cipherData = null; if (pdu.GetType() == typeof(Token4121)) { cipherData = pdu.ToBytes(); } else { byte[] allData = pdu.ToBytes(); byte[] paddingData = ((Token1964_4757)pdu).paddingData; cipherData = ArrayUtility.SubArray(allData, 0, allData.Length - paddingData.Length); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, paddingData); } SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Data, ArrayUtility.SubArray(cipherData, cipherData.Length - message.Length)); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, ArrayUtility.SubArray(cipherData, 0, cipherData.Length - message.Length)); }
/// <summary> /// Decrypt a request or response /// </summary> /// <param name="securityBuffers">Security buffers containing encrypted data.</param> /// <param name="sentFromClient">True if the token is a request, false is a response</param> /// <returns>Plain-text data.</returns> private byte[] Decrypt(SecurityBuffer[] securityBuffers, bool sentFromClient) { KileContext context = sentFromClient ? (KileContext)kileDecoder.serverContext : (KileContext)kileDecoder.clientContext; KileRole.GssUnWrapEx(context, securityBuffers); return(SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Data)); }
/// <summary> /// This takes the given SecurityBuffer array, signs data part, and updates signature into token part /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">Data to sign and token to update.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static void Sign(KileRole kileRole, params SecurityBuffer[] securityBuffers) { byte[] token = SspiUtility.ConcatenateReadWriteSecurityBuffers(securityBuffers, SecurityBufferType.Token); if (token.Length == 0) { throw new ArgumentException("No token can be updated for signature."); } byte[] message = GetToBeSignedDataFromSecurityBuffers(securityBuffers); SGN_ALG sgnAlg = GetSgnAlg(kileRole); KilePdu pdu = kileRole.GssGetMic(sgnAlg, message); byte[] signature = pdu.ToBytes(); SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Token, signature); }
/// <summary> /// Get SGN_ALG for encryption and sign. /// </summary> /// <returns>The SGN_ALG got from context.</returns> /// <exception cref="System.FormatException">Thrown when the key is not valid.</exception> private static SGN_ALG GetSgnAlg(KileRole kileRole) { EncryptionKey key = kileRole.Context.ContextKey; if (key == null || key.keytype == null || key.keyvalue == null || key.keyvalue.Value == null) { throw new FormatException("Initialization is not complete successfully!"); } SGN_ALG sgnAlg = SGN_ALG.HMAC; EncryptionType type = (EncryptionType)key.keytype.Value; if (type == EncryptionType.DES_CBC_MD5 || type == EncryptionType.DES_CBC_CRC) { sgnAlg = SGN_ALG.DES_MAC_MD5; } return(sgnAlg); }
/// <summary> /// This takes the given byte array, decrypts it, and returns /// the original, unencrypted byte array. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">The security buffers to decrypt.</param> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static bool Decrypt(KileRole kileRole, params SecurityBuffer[] securityBuffers) { KilePdu pdu = kileRole.GssUnWrapEx(securityBuffers); byte[] decryptedMessage = null; if (pdu.GetType() == typeof(Token4121)) { decryptedMessage = ((Token4121)pdu).Data; } else if (pdu.GetType() == typeof(Token1964_4757)) { Token1964_4757 tokenData = (Token1964_4757)pdu; decryptedMessage = tokenData.Data; SspiUtility.UpdateSecurityBuffers(securityBuffers, SecurityBufferType.Padding, tokenData.paddingData); } // else do nothing return(true); }
/// <summary> /// Decrypt a request or response /// </summary> /// <param name="token">A token containing encrypted data.</param> /// <param name="sentFromClient">True if the token is a request, false is a response</param> /// <returns>Plain-text data.</returns> private byte[] Decrypt(byte[] token, bool sentFromClient) { KileContext context = sentFromClient ? (KileContext)kileDecoder.serverContext : (KileContext)kileDecoder.clientContext; KilePdu pdu = KileRole.GssUnWrap(context, token); Token4121 token4121Pdu = pdu as Token4121; if (token4121Pdu != null) { return(token4121Pdu.Data); } Token1964_4757 token1964or4757Pdu = pdu as Token1964_4757; if (token1964or4757Pdu != null) { return(token1964or4757Pdu.Data); } throw new InvalidOperationException("Token type is not supported."); }
/// <summary> /// Create a KileDecrypter instance. /// User should call following methods in sequence to initialize: AsExchange, TgsExchange and ApExchange. /// After exchanges are done, call DecryptRequest or DecryptResponse from first encrypted message to last. /// Do not skip any request or response. /// </summary> /// <param name="domain"> /// The realm part of the client's principal identifier. /// This argument cannot be null. /// </param> /// <param name="cName"> /// The account to logon the remote machine. Either user account or computer account. /// This argument cannot be null. /// </param> /// <param name="password"> /// The password of the user. /// This argument cannot be null. /// </param> /// <param name="accountType"> /// The type of the logon account. User or Computer. /// </param> /// <param name="connectionType"> /// The connection type, TCP or UDP. /// </param> /// <exception cref="System.ArgumentNullException"> /// Thrown when any parameter is null. /// </exception> public KileDecrypter( string domain, string cName, string password, KileAccountType accountType, KileConnectionType connectionType) { if (domain == null) { throw new ArgumentNullException(nameof(domain)); } if (cName == null) { throw new ArgumentNullException(nameof(cName)); } if (password == null) { throw new ArgumentNullException(nameof(password)); } kileDecoder = new KileDecoder(); kileDecoder.connectionType = connectionType; string salt = KileRole.GenerateSalt(domain, cName, accountType); kileDecoder.clientContext = new KileClientContext(); kileDecoder.clientContext.Password = password; kileDecoder.clientContext.TransportType = connectionType; kileDecoder.clientContext.Salt = salt; kileDecoder.serverContext = new KileServerContext(); kileDecoder.serverContext.TransportType = connectionType; kileDecoder.serverContext.Salt = salt; kileDecoder.serverContextList = new Dictionary <KileConnection, KileServerContext>(new KileServerContextComparer()); kileDecoder.serverContextList.Add(new KileConnection(FAKE_ENDPOINT), kileDecoder.serverContext); }
/// <summary> /// This takes the given byte array and verifies it using the SSPI VerifySignature method. /// </summary> /// <param name="kileRole">Represents client or server</param> /// <param name="securityBuffers">Data and token to verify</param> /// <returns>Success if true, Fail if false</returns> /// <exception cref="System.ArgumentException">Thrown when the data or token is not valid.</exception> internal static bool Verify(KileRole kileRole, params SecurityBuffer[] securityBuffers) { KilePdu pdu; return(kileRole.GssVerifyMicEx(securityBuffers, out pdu)); }