C#实现b64_sha1加密算法

由于工作需要,必须在.net上实现b64_sha1加密,网上只有js版和java版,无奈自己用java翻译出了一份,中间遇到的问题是java的无符号右移位运算在C#中没有对应方法,又自己实现了一套。现在贴出代码,供大家参考。js版本网上很多,就不贴了。


    public class B64sha1
    {
        private static bool hexcase = false;
        private static string b64pad = "";
        private static int chrsz = 16;

        // public static string hex_sha1(string s){return binb2hex(core_sha1(str2binb(s),s.Length * chrsz));}
        public static string b64_sha1(string s) { return binb2b64(core_sha1(str2binb(s), s.Length * chrsz)); }
        // public static string str_sha1(string s){return binb2str(core_sha1(str2binb(s),s.Length * chrsz));}
        // public static string hex_hmac_sha1(string key, string data){ return binb2hex(core_hmac_sha1(key, data));}
        // public static string b64_hmac_sha1(string key, string data){ return binb2b64(core_hmac_sha1(key, data));}
        // public static string str_hmac_sha1(string key, string data){ return binb2str(core_hmac_sha1(key, data));}


        private static int foo(int x, int y)
        {
            int mask = 0x7fffffff;
            for (int i = 0; i < y; i++)
            {
                x >>= 1;
                x &= mask;
            }
            return x;
        }

        private static char charAt(string s, int index)
        {
            char[] array = s.ToCharArray();
            return array[index];
        }


        private static string binb2b64(int[] binarray)
        {
            string tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
            string str = "";
            binarray = strechbinarray(binarray, binarray.Length * 4);

            for (int i = 0; i < binarray.Length * 4; i += 3)
            {
                int triplet = (((binarray[i >> 2] >> 8 * (3 - i % 4)) & 0xff) << 16)
                    | (((binarray[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xff) << 8)
                    | ((binarray[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xff);

                for (int j = 0; j < 4; j++)
                {
                    if (i * 8 + j * 6 > binarray.Length * 32)
                    {
                        str += b64pad;
                    }
                    else
                    {
                        str += charAt(tab, (triplet >> 6 * (3 - j)) & 0x3f);
                    }
                }
            }
            return cleanb64str(str);
        }

        private static string binb2hex(int[] binarray)
        {
            string hex_tab = hexcase ? "0123456789abcdef" : "0123456789abcdef";
            string str = "";

            for (int i = 0; i < binarray.Length * 4; i++)
            {
                char a = charAt(hex_tab, (binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xf);
                char b = charAt(hex_tab, (binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xf);
                str += a.ToString() + b.ToString();
            }
            return str;
        }

        private static string binb2str(int[] bin)
        {
            string str = "";
            int mask = (1 << chrsz) - 1;

            for (int i = 0; i < bin.Length * 32; i += chrsz)
            {
                str += Convert.ToChar(foo(bin[i >> 5], (24 - i % 32)) & mask);
            }
            return str;
        }

        private static int bit_rol(int num, int cnt)
        {
            return (num << cnt) | foo(num, 32 - cnt);
        }

        private static string cleanb64str(string str)
        {
            str = (str == null) ? "" : str;
            int len = str.Length;

            if (len <= 1)
            {
                return str;
            }

            char trailchar = charAt(str, len - 1);
            string trailstr = "";

            for (int i = len - 1; i >= 0 && charAt(str, i) == trailchar; i--)
            {
                trailstr += charAt(str, i);
            }
            return str.Substring(0, str.IndexOf(trailstr));
        }

        private static int[] complete216(int[] oldbin)
        {
            if (oldbin.Length >= 16)
            {
                return oldbin;
            }

            int[] newbin = new int[16 - oldbin.Length];

            for (int i = 0; i < newbin.Length; newbin[i] = 0, i++) ;

            return concat(oldbin, newbin);
        }

        private static int[] concat(int[] oldbin, int[] newbin)
        {
            int[] retval = new int[oldbin.Length + newbin.Length];

            for (int i = 0; i < (oldbin.Length + newbin.Length); i++)
            {
                if (i < oldbin.Length)
                {
                    retval[i] = oldbin[i];
                }
                else
                {
                    retval[i] = newbin[i - oldbin.Length];
                }
            }
            return retval;
        }

        private static int[] core_hmac_sha1(String key, String data)
        {
            key = (key == null) ? "" : key;
            data = (data == null) ? "" : data;
            int[] bkey = complete216(str2binb(key));

            if (bkey.Length > 16)
            {
                bkey = core_sha1(bkey, key.Length * chrsz);
            }

            int[] ipad = new int[16];
            int[] opad = new int[16];

            for (int i = 0; i < 16; ipad[i] = 0, opad[i] = 0, i++) ;

            for (int i = 0; i < 16; i++)
            {
                ipad[i] = bkey[i] ^ 0x36363636;
                opad[i] = bkey[i] ^ 0x5c5c5c5c;
            }

            int[] hash = core_sha1(concat(ipad, str2binb(data)), 512 + data.Length * chrsz);

            return core_sha1(concat(opad, hash), 512 + 160);
        }

        private static int[] core_sha1(int[] x, int len)
        {
            int size = (len >> 5);
            x = strechbinarray(x, size);
            x[len >> 5] |= 0x80 << (24 - len % 32);
            size = ((len + 64 >> 9) << 4) + 15;
            x = strechbinarray(x, size);
            x[((len + 64 >> 9) << 4) + 15] = len;

            int[] w = new int[80];
            int a = 1732584193;
            int b = -271733879;
            int c = -1732584194;
            int d = 271733878;
            int e = -1009589776;

            for (int i = 0; i < x.Length; i += 16)
            {
                int olda = a;
                int oldb = b;
                int oldc = c;
                int oldd = d;
                int olde = e;

                for (int j = 0; j < 80; j++)
                {
                    if (j < 16)
                    {
                        w[j] = x[i + j];
                    }
                    else
                    {
                        w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
                    }

                    int t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j)));

                    e = d;
                    d = c;
                    c = rol(b, 30);
                    b = a;
                    a = t;
                }

                a = safe_add(a, olda);
                b = safe_add(b, oldb);
                c = safe_add(c, oldc);
                d = safe_add(d, oldd);
                e = safe_add(e, olde);
            }

            int[] retval = new int[5];

            retval[0] = a;
            retval[1] = b;
            retval[2] = c;
            retval[3] = d;
            retval[4] = e;

            return retval;
        }

        private static int safe_add(int x, int y)
        {
            int lsw = (int)(x & 0xffff) + (int)(y & 0xffff);
            int msw = (x >> 16) + (y >> 16) + (lsw >> 16);

            return (msw << 16) | (lsw & 0xffff);
        }

        private static int[] strechbinarray(int[] oldbin, int size)
        {
            int currlen = oldbin.Length;

            if (currlen >= size + 1)
            {
                return oldbin;
            }

            int[] newbin = new int[size + 1];
            for (int i = 0; i < size; newbin[i] = 0, i++) ;

            for (int i = 0; i < currlen; i++)
            {
                newbin[i] = oldbin[i];
            }

            return newbin;
        }

        private static int[] str2binb(String str)
        {
            str = (str == null) ? "" : str;

            int[] tmp = new int[str.Length * chrsz];
            int mask = (1 << chrsz) - 1;

            for (int i = 0; i < str.Length * chrsz; i += chrsz)
            {
                tmp[i >> 5] |= ((int)(charAt(str, i / chrsz)) & mask) << (32 - chrsz - i % 32);
            }

            int len = 0;
            for (int i = 0; i < tmp.Length && tmp[i] != 0; i++, len++) ;

            int[] bin = new int[len];

            for (int i = 0; i < len; i++)
            {
                bin[i] = tmp[i];
            }

            return bin;
        }

        private static int rol(int num, int cnt)
        {
            return (num << cnt) | foo(num, 32 - cnt);
        }

        private static int sha1_ft(int t, int b, int c, int d)
        {
            if (t < 20)
                return (b & c) | ((~b) & d);

            if (t < 40)
                return b ^ c ^ d;

            if (t < 60)
                return (b & c) | (b & d) | (c & d);

            return b ^ c ^ d;
        }

        private static int sha1_kt(int t)
        {
            return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514;
        }


    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值