zoukankan      html  css  js  c++  java
  • [c#] WebQQ密码MD5加密算法的C#实现

        应网友之邀为大家提供一下WebQQ的MD5加密算法,因为MD5是WebQQ模拟登录过程中最难的部分,所以在这里不能不提及。本文只能提供C#的实现方法,其他语言版本可以参照C#作适当的修改便可。要操作MD5,C#中自带一个MD5类可供选择,相当方便。如果要自己写算法实现MD5也未曾不可,只是放着现成的类不用太浪费了。

    首先引用空间:

    using System.Security.Cryptography;

    先说说WebQQ MD5加密的方式,公式是这样的:

    md5(md5(hexchar2bin(md5(p)) + uin) + verify.toUpperCase());
    verify是验证码,uin就是那段\x0的代码,p是密码

    至于为什么是这样,作为菜鸟,我也说不清,懵里懵懂的给大家展示一下~!~只是用firebug分析到的Js里面的算法大致就是这个意思。其中这里最关键的函数,就是hexchar2bin了.我们先来罗列一下基础的MD5函数吧,其实是MD5的标准算法,直接贴在下面了,将普通文本转换成MD5。

    View Code
      /// <summary>
            /// 一次md5加密
          ///http://www.cnblogs.com/uu102
            /// </summary>
            /// <param name="md5_str">需要加密的文本</param>
            /// <returns></returns>
            public static string MD5_Encrypt(string md5_str)
            {
                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(md5_str);
                byte[] bytes1 = md5.ComputeHash(bytes);
    
                System.Text.StringBuilder stringBuilder = new StringBuilder();
                foreach (var item in bytes1)
                {
                    stringBuilder.Append(item.ToString("x").PadLeft(2, '0'));
                }
                return stringBuilder.ToString().ToUpper();
            }

    再重载一次这个方法,以便能将字节数组也能转换成我们需要的MD5字符串

    View Code
    /// <summary>
            /// 将字节流加密
            /// </summary>
            /// <param name="md5_bytes">需要加密的字节流</param>
            /// <returns></returns>
            private static string MD5_Encrypt(byte[] md5_bytes)
            {
                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
    
                byte[] bytes1 = md5.ComputeHash(md5_bytes);
                System.Text.StringBuilder stringBuilder = new StringBuilder();
                foreach (var item in bytes1)
                {
                    stringBuilder.Append(item.ToString("x").PadLeft(2, '0'));
                }
                return stringBuilder.ToString().ToUpper();
    
            }

    接着,再上一个将字符串转换为MD5加密数组的函数

    View Code
     /// <summary>
            /// 获取文本的md5字节流
            /// </summary>
            /// <param name="md5_str">需要加密成Md5d的文本</param>
            /// <returns></returns>
            private static byte[] MD5_GetBytes(string md5_str)
            {
                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(md5_str);
                return md5.ComputeHash(bytes);
    
    
            }

    接下来

    View Code
    /// <summary>
            /// 加密成md5字节流之后转换成文本
            /// </summary>
            /// <param name="md5_str"></param>
            /// <returns></returns>
            private static string Encrypt_1(string md5_str)
            {
                System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5CryptoServiceProvider.Create();
                byte[] bytes = System.Text.Encoding.ASCII.GetBytes(md5_str);
                bytes = md5.ComputeHash(bytes);
                System.Text.StringBuilder stringBuilder = new StringBuilder();
                foreach (var item in bytes)
                {
                    stringBuilder.Append(@"\x");
                    stringBuilder.Append(item.ToString("x2"));
                }
                return stringBuilder.ToString();
            }

    操作字节流

    View Code
    public class ByteBuffer
        {
            private byte[] _buffer;
            /// <summary>
            /// 获取同后备存储区连接的基础流
            /// </summary>
            public Stream BaseStream;
    
            /// <summary>
            /// 构造函数
            /// </summary>
            public ByteBuffer()
            {
                this.BaseStream = new MemoryStream();
                this._buffer = new byte[0x10];
            }
    
            /// <summary>
            /// 设置当前流中的位置
            /// </summary>
            /// <param name="offset">相对于origin参数字节偏移量</param>
            /// <param name="origin">System.IO.SeekOrigin类型值,指示用于获取新位置的参考点</param>
            /// <returns></returns>
            public virtual long Seek(int offset, SeekOrigin origin)
            {
                return this.BaseStream.Seek((long)offset, origin);
            }
    
    
    
            /// <summary>
            /// 检测是否还有可用字节
            /// </summary>
            /// <returns></returns>
            public bool Peek()
            {
                return BaseStream.Position >= BaseStream.Length ? false : true;
            }
    
            /// <summary>
            /// 将整个流内容写入字节数组,而与 Position 属性无关。
            /// </summary>
            /// <returns></returns>
            public byte[] ToByteArray()
            {
                long org = BaseStream.Position;
                BaseStream.Position = 0;
                byte[] ret = new byte[BaseStream.Length];
                BaseStream.Read(ret, 0, ret.Length);
                BaseStream.Position = org;
                return ret;
            }
    
    
            #region "写流方法"
            /// <summary>
            /// 压入一个布尔值,并将流中当前位置提升1
            /// </summary>
            /// <param name="value"></param>
            public void Put(bool value)
            {
                this._buffer[0] = value ? (byte)1 : (byte)0;
                this.BaseStream.Write(_buffer, 0, 1);
            }
    
            /// <summary>
            /// 压入一个Byte,并将流中当前位置提升1
            /// </summary>
            /// <param name="value"></param>
            public void Put(Byte value)
            {
                this.BaseStream.WriteByte(value);
            }
            /// <summary>
            /// 压入Byte数组,并将流中当前位置提升数组长度
            /// </summary>
            /// <param name="value">字节数组</param>
            public void Put(Byte[] value)
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                this.BaseStream.Write(value, 0, value.Length);
            }
            /// <summary>
            /// Puts the int.
            /// </summary>
            /// <param name="value">The value.</param>
            public void PutInt(int value)
            {
                PutInt((uint)value);
            }
            /// <summary>
            /// 压入一个int,并将流中当前位置提升4
            /// </summary>
            /// <param name="value"></param>
            public void PutInt(uint value)
            {
                this._buffer[0] = (byte)(value >> 0x18);
                this._buffer[1] = (byte)(value >> 0x10);
                this._buffer[2] = (byte)(value >> 8);
                this._buffer[3] = (byte)value;
                this.BaseStream.Write(this._buffer, 0, 4);
            }
            /// <summary>
            /// Puts the int.
            /// </summary>
            /// <param name="index">The index.</param>
            /// <param name="value">The value.</param>
            public void PutInt(int index, uint value)
            {
                int pos = (int)this.BaseStream.Position;
                Seek(index, SeekOrigin.Begin);
                PutInt(value);
                Seek(pos, SeekOrigin.Begin);
            }
    
            #endregion
    
            #region "读流方法"
    
            /// <summary>
            /// 读取Byte值,并将流中当前位置提升1
            /// </summary>
            /// <returns></returns>
            public byte Get()
            {
                return (byte)BaseStream.ReadByte();
            }
    
            #endregion
    
    
        }

    最后一个函数

    View Code
      public static string MD5_QQ_2_Encrypt(long uin, string password, string verifyCode)
            {
    
                ByteBuffer buffer= new ByteBuffer();
                 buffer.Put(MD5_GetBytes(password));
                //buffer.Put(Encoding.UTF8.GetBytes(password));
                buffer.PutInt(0);
                buffer.PutInt((uint)uin);
                byte[] bytes = buffer.ToByteArray();
                string md5_1 = MD5_Encrypt(bytes);//将混合后的字节流进行一次md5加密
                string result= MD5_Encrypt(md5_1 + verifyCode.ToUpper());//再用加密后的结果与大写的验证码一起加密一次
                return result;
    
            }

     大家凑合着看吧。对于这些代码实在是没什么话说,只好让各位自行研究了。代码绝对可用。本人博客每天都有原创更新,欢迎大家继续关注!



    ///******************************************************
    ///本文作者:凌晨的搜索者
    ///博客地址:http://www.cnblogs.com/uu102
    ///本文属于原创,如果有您需要的内容想要转载,请保留此段签名注释,否则作者将保留追究法律责任的权利。
    ///******************************************************
  • 相关阅读:
    P5049 旅行(数据加强版)(基环树)
    P5024 保卫王国(动态dp/整体dp/倍增dp)
    CF891C Envy(离线/在线+可撤销并查集/并查集/LCT)
    CF1217题解
    CF1215题解
    浅谈bitset
    CF1214题解
    CF1213F Unstable String Sort(差分)
    C++创建和使用动态链接库
    交叉编译openssl1.1.1a
  • 原文地址:https://www.cnblogs.com/uu102/p/2687959.html
Copyright © 2011-2022 走看看