/// <summary> /// Computes the MD5 checksum of the content. /// </summary> /// <remarks> /// Computes the MD5 checksum of the MIME content in its canonical /// format and then base64-encodes the result. /// </remarks> /// <returns>The md5sum of the content.</returns> /// <exception cref="System.InvalidOperationException"> /// The <see cref="ContentObject"/> is <c>null</c>. /// </exception> public string ComputeContentMd5() { if (ContentObject == null) { throw new InvalidOperationException("Cannot compute Md5 checksum without a ContentObject."); } using (var stream = ContentObject.Open()) { byte[] checksum; using (var filtered = new FilteredStream(stream)) { if (ContentType.IsMimeType("text", "*")) { filtered.Add(new Unix2DosFilter()); } using (var md5 = MD5.Create()) checksum = md5.ComputeHash(filtered); } var base64 = new Base64Encoder(true); var digest = new byte[base64.EstimateOutputLength(checksum.Length)]; int n = base64.Flush(checksum, 0, checksum.Length, digest); return(Encoding.ASCII.GetString(digest, 0, n)); } }
static void ComputeNtlmV2Session(string password, byte[] challenge, out byte[] lm, out byte[] ntlm) { var nonce = new byte[8]; using (var rng = RandomNumberGenerator.Create()) rng.GetBytes(nonce); var sessionNonce = new byte[challenge.Length + 8]; challenge.CopyTo(sessionNonce, 0); nonce.CopyTo(sessionNonce, challenge.Length); lm = new byte[24]; nonce.CopyTo(lm, 0); using (var md5 = MD5.Create()) { var hash = md5.ComputeHash(sessionNonce); var newChallenge = new byte[8]; Array.Copy(hash, newChallenge, 8); ntlm = ComputeNtlm(password, newChallenge); // clean up Array.Clear(newChallenge, 0, newChallenge.Length); Array.Clear(hash, 0, hash.Length); } // clean up Array.Clear(sessionNonce, 0, sessionNonce.Length); Array.Clear(nonce, 0, nonce.Length); }
static SaslMechanism() { try { using (var md5 = MD5.Create()) md5supported = true; } catch { md5supported = false; } // Note: It's probably arguable that NTLM is more secure than SCRAM but the odds of a server supporting both is probably low. var supported = new List <string> { "SCRAM-SHA-512", "SCRAM-SHA-256", "SCRAM-SHA-1", "NTLM" }; if (md5supported) { supported.Add("DIGEST-MD5"); supported.Add("CRAM-MD5"); } supported.Add("PLAIN"); supported.Add("LOGIN"); RankedAuthenticationMechanisms = supported.ToArray(); }
static SaslMechanism() { try { using (var md5 = MD5.Create()) md5supported = true; } catch { md5supported = false; } }
public string ComputeHash(string password, bool client) { string text, a1, a2; byte[] buf, digest; // compute A1 text = string.Format("{0}:{1}:{2}", UserName, Realm, password); buf = Encoding.UTF8.GetBytes(text); using (var md5 = MD5.Create()) digest = md5.ComputeHash(buf); using (var md5 = MD5.Create()) { md5.TransformBlock(digest, 0, digest.Length, null, 0); text = string.Format(":{0}:{1}", Nonce, CNonce); if (!string.IsNullOrEmpty(AuthZid)) { text += ":" + AuthZid; } buf = Encoding.ASCII.GetBytes(text); md5.TransformFinalBlock(buf, 0, buf.Length); a1 = HexEncode(md5.Hash); } // compute A2 text = client ? "AUTHENTICATE:" : ":"; text += DigestUri; if (Qop == "auth-int" || Qop == "auth-conf") { text += ":00000000000000000000000000000000"; } buf = Encoding.ASCII.GetBytes(text); using (var md5 = MD5.Create()) digest = md5.ComputeHash(buf); a2 = HexEncode(digest); // compute KD text = string.Format("{0}:{1}:{2:x8}:{3}:{4}:{5}", a1, Nonce, Nc, CNonce, Qop, a2); buf = Encoding.ASCII.GetBytes(text); using (var md5 = MD5.Create()) digest = md5.ComputeHash(buf); return(HexEncode(digest)); }
/// <summary> /// Parses the server's challenge token and returns the next challenge response. /// </summary> /// <remarks> /// Parses the server's challenge token and returns the next challenge response. /// </remarks> /// <returns>The next challenge response.</returns> /// <param name="token">The server's challenge token.</param> /// <param name="startIndex">The index into the token specifying where the server's challenge begins.</param> /// <param name="length">The length of the server's challenge.</param> /// <exception cref="System.InvalidOperationException"> /// The SASL mechanism is already authenticated. /// </exception> /// <exception cref="System.NotSupportedException"> /// The SASL mechanism does not support SASL-IR. /// </exception> /// <exception cref="SaslException"> /// An error has occurred while parsing the server's challenge token. /// </exception> protected override byte[] Challenge(byte[] token, int startIndex, int length) { if (IsAuthenticated) { throw new InvalidOperationException(); } if (token == null) { throw new NotSupportedException("CRAM-MD5 does not support SASL-IR."); } var userName = Encoding.UTF8.GetBytes(Credentials.UserName); var password = Encoding.UTF8.GetBytes(Credentials.Password); var ipad = new byte[64]; var opad = new byte[64]; byte[] digest; if (password.Length > 64) { byte[] checksum; using (var md5 = MD5.Create()) checksum = md5.ComputeHash(password); Array.Copy(checksum, ipad, checksum.Length); Array.Copy(checksum, opad, checksum.Length); } else { Array.Copy(password, ipad, password.Length); Array.Copy(password, opad, password.Length); } Array.Clear(password, 0, password.Length); for (int i = 0; i < 64; i++) { ipad[i] ^= 0x36; opad[i] ^= 0x5c; } using (var md5 = MD5.Create()) { md5.TransformBlock(ipad, 0, ipad.Length, null, 0); md5.TransformFinalBlock(token, startIndex, length); digest = md5.Hash; } using (var md5 = MD5.Create()) { md5.TransformBlock(opad, 0, opad.Length, null, 0); md5.TransformFinalBlock(digest, 0, digest.Length); digest = md5.Hash; } var buffer = new byte[userName.Length + 1 + (digest.Length * 2)]; int offset = 0; for (int i = 0; i < userName.Length; i++) { buffer[offset++] = userName[i]; } buffer[offset++] = 0x20; for (int i = 0; i < digest.Length; i++) { byte c = digest[i]; buffer[offset++] = HexAlphabet[(c >> 4) & 0x0f]; buffer[offset++] = HexAlphabet[c & 0x0f]; } IsAuthenticated = true; return(buffer); }