正在做一个软件需要用到非对称加密算法进行注册信息的加密,没想到的是RSA只能用公钥加密私钥解密,这和我的需求正好相反,于是在网上找到了牛人做的加密算法,可在使用后发现,对中文的支持有问题。

原文地址:http://www.cnblogs.com/hhh/archive/2011/06/03/2070692.html

原来的算法将输入字符串按每段128个字符进行拆解,可是如果在拆分的位置上正好有中文,解密之后就会出现乱码,甚是头疼。

仔细研究过算法以后,发现原先以字符串方式来处理数据的方式并不合理,于是重写了算法,以二进制方式处理,成功解决了乱码的问题,以下是改进之后的算法。

        public static byte[] Encrypt(byte[] data, BigInteger d, BigInteger n)
        {
            int size = 128;
            byte[] buffer = new byte[size];

            using (MemoryStream source = new MemoryStream(data))
            using (MemoryStream output = new MemoryStream())
            {
                int bytes;

                while ((bytes = source.Read(buffer, 0, size)) > 0)
                {
                    BigInteger bi1 = new BigInteger(buffer, bytes);
                    BigInteger bi2 = bi1.modPow(d, n);

                    data = bi2.getBytes();
                    System.Diagnostics.Debug.Assert(data.Length < 256);
                    output.WriteByte((byte)data.Length);
                    output.Write(data, 0, data.Length);
                }

                return output.ToArray();
            }
        }

        public static byte[] Decrypt(byte[] data, BigInteger e, BigInteger n)
        {
            using (MemoryStream input = new MemoryStream(data))
            using (MemoryStream output = new MemoryStream())
            {
                int length;

                while ((length = input.ReadByte()) >= 0)
                {
                    byte[] buffer = new byte[length];
                    if (input.Read(buffer, 0, length) != length)
                        throw new InvalidDataException();

                    BigInteger bi1 = new BigInteger(buffer);
                    BigInteger bi2 = bi1.modPow(e, n);

                    buffer = bi2.getBytes();

                    output.Write(buffer, 0, buffer.Length);
                }

                return output.ToArray();
            }
        }

        public static string Encrypt(string source, string d, string n)
        {
            byte[] N = Convert.FromBase64String(n);
            byte[] D = Convert.FromBase64String(d);
            BigInteger biN = new BigInteger(N);
            BigInteger biD = new BigInteger(D);

            byte[] data = System.Text.Encoding.UTF8.GetBytes(source);
            data = Encrypt(data, biD, biN);

            return Convert.ToBase64String(data);
        }

        public static string Decrypt(string source, string e, string n)
        {
            byte[] N = Convert.FromBase64String(n);
            byte[] E = Convert.FromBase64String(e);
            BigInteger biN = new BigInteger(N);
            BigInteger biE = new BigInteger(E);
            
            byte[] data = Convert.FromBase64String(source);
            data = Decrypt(data, biE, biN);

            return System.Text.Encoding.UTF8.GetString(data);
        }  

最后,感谢原作者的努力,让我省了好多事。

参考文章:

【1】RSA私钥加密公钥解密算法

【2】C#使用RSA私钥加密公钥解密的改进,解决特定情况下解密后出现乱码的问题

【3】BigInteger大整数运算类

posted on 2013-04-21 01:02  一风  阅读(803)  评论(0编辑  收藏  举报