blob: 7e310c536451add1e86598b11998c3a8cb24c540 [file] [log] [blame]
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
using System;
using System.Security.Cryptography;
namespace Apache.Qpid.Sasl
{
/// <summary>
/// Rough HMAC MD5 implementation as presented in
/// RFC 2104. Used because the HMACMD5 class in the
/// .NET framework is not available in v1.1.
/// </summary>
public sealed class MD5HMAC : IDisposable
{
private const int BLOCK_LEN = 64;
private MD5 _hash;
private byte[] _key;
private byte[] _ipad;
private byte[] _opad;
public MD5HMAC(byte[] key)
{
if ( key == null || key.Length == 0 )
throw new ArgumentNullException("key");
_hash = new MD5CryptoServiceProvider();
byte[] theKey = key;
if ( theKey.Length > BLOCK_LEN )
{
theKey = _hash.ComputeHash(theKey);
}
// pad key with 0's up to BLOCK_LEN
_key = new byte[BLOCK_LEN];
Array.Copy(theKey, _key, theKey.Length);
CreatePads();
}
public byte[] ComputeHash(byte[] input)
{
// H(K XOR opad, H(K XOR ipad, text))
return H(_opad, H(_ipad, input));
}
public void Dispose()
{
if ( _hash != null )
{
((IDisposable)_hash).Dispose();
_hash = null;
}
}
#region Private Methods
//
// Private Methods
//
private void CreatePads()
{
_ipad = new byte[BLOCK_LEN];
_opad = new byte[BLOCK_LEN];
for ( int i = 0; i < BLOCK_LEN; i++ )
{
_ipad[i] = 0x36;
_opad[i] = 0x5c;
}
XOR(_ipad, _key);
XOR(_opad, _key);
}
private static void XOR(byte[] dest, byte[] other)
{
// assume both are same size
for ( int i = 0; i < dest.Length; i++ )
{
dest[i] ^= other[i];
}
}
private byte[] H(byte[] v1, byte[] v2)
{
byte[] total = new byte[v1.Length + v2.Length];
Array.Copy(v1, total, v1.Length);
Array.Copy(v2, 0, total, v1.Length, v2.Length);
return _hash.ComputeHash(total);
}
#endregion // Private Methods
} // class MD5HMAC
} // namespace Apache.Qpid.Sasl