3DES 加密解密

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Pkcs;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.X509;
using System;
using System.Collections.Generic;
using System.Text;
     /// <summary>
    /// 加密文本类型
    /// </summary>
    public enum CryptoTextType
    {
        Invalid = -1,
        Hex,
        Base64,
        Base62,
        Base62V2,
        Count,
    }

    public enum DesEdeKeyLen
    {
        KL112 = 112,
        KL168 = 168,
        KL192 = 192
    }
     /// <summary>
    /// 3DES 加密解密
    /// </summary>
    public class BouncyCastleDesEdeUtils
    {
        /// <summary>
        /// key 合法长度  DesEdeKeyLen
        /// </summary>
        /// <param name="KELen"></param>
        /// <returns></returns>
        public static bool GenerationKey(ref String key,DesEdeKeyLen KELen = DesEdeKeyLen.KL192,
            CryptoTextType cType = CryptoTextType.Base64)
        {
            SecureRandom sr = new SecureRandom();
            KeyGenerationParameters kgp = new KeyGenerationParameters(
                sr,(int)KELen);
            DesEdeKeyGenerator kg = new DesEdeKeyGenerator();
            kg.Init(kgp);
            byte[] bskey = kg.GenerateKey();
            bool ret =  DesEdeParameters.IsRealEdeKey(bskey, 0);
            key = String.Empty;
            switch (cType)
            {
                case CryptoTextType.Hex:
                    key = Hex.ToHexString(bskey);
                    break;
                case CryptoTextType.Base64:
                    key = Convert.ToBase64String(bskey);
                    break;
                case CryptoTextType.Base62:
                    key = EncodingExtensions.ToBase62(bskey);
                    break;
                case CryptoTextType.Base62V2:
                    key = EncodingExtensions.ToBase62V2(bskey);
                    break;
                default:
                    key = Convert.ToBase64String(bskey);
                    break;
            }
            return ret;
        }

        public static String EncryptByKey(String key, String data,
            CryptoTextType keyType = CryptoTextType.Base64,
            CryptoTextType dataType = CryptoTextType.Base64
            )
        {
            byte[] bsKey = null;
            switch (keyType)
            {
                case CryptoTextType.Hex:
                    bsKey = Hex.Decode(key);
                    break;
                case CryptoTextType.Base64:
                    bsKey = Convert.FromBase64String(key);
                    break;
                case CryptoTextType.Base62:
                    bsKey = EncodingExtensions.FromBase62(key);
                    break;
                case CryptoTextType.Base62V2:
                    bsKey = EncodingExtensions.FromBase62V2(key);
                    break;
                default:
                    bsKey = Convert.FromBase64String(key);
                    break;
            }

            byte[] bsData = null;
            switch (dataType)
            {
                case CryptoTextType.Hex:
                    bsData = Hex.Decode(data);
                    break;
                case CryptoTextType.Base64:
                    bsData = Convert.FromBase64String(data);
                    break;
                case CryptoTextType.Base62:
                    bsData = EncodingExtensions.FromBase62(data);
                    break;
                case CryptoTextType.Base62V2:
                    bsData = EncodingExtensions.FromBase62V2(data);
                    break;
                default:
                    bsData = Convert.FromBase64String(data);
                    break;
            }

            string encode = EncryptByKey(bsKey, bsData, dataType);
            return encode;
        }
        public static String EncryptByKey(byte[] hex_key, byte[] hex_data,
            CryptoTextType cType = CryptoTextType.Base64)
        {
            try
            {
                PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                new CbcBlockCipher(new DesEdeEngine()));
                cipher.Init(true, new DesEdeParameters(hex_key));
                byte[] encryptBytes = cipher.DoFinal(hex_data, 0, hex_data.Length);
                string encode = string.Empty;
                switch (cType)
                {
                    case CryptoTextType.Hex:
                        encode = BitConverter.ToString(encryptBytes).Replace("-", "");
                        break;
                    case CryptoTextType.Base64:
                        encode = Convert.ToBase64String(encryptBytes);
                        break;
                    case CryptoTextType.Base62:
                        encode = EncodingExtensions.ToBase62(encryptBytes);
                        break;
                    case CryptoTextType.Base62V2:
                        encode = EncodingExtensions.ToBase62V2(encryptBytes);
                        break;
                    default:
                        encode = Convert.ToBase64String(encryptBytes);
                        break;
                }
                return encode;
            }
            catch(Exception)
            {

            }
                    
            return "";
        }

        public static String DecryptByKey(byte[] hex_key, byte[] hex_data, 
            CryptoTextType cType = CryptoTextType.Base64)
        {
            try
            {
                PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(
                new CbcBlockCipher(new DesEdeEngine()));
                cipher.Init(false, new DesEdeParameters(hex_key));
                byte[] encryptBytes = cipher.DoFinal(hex_data, 0, hex_data.Length);
                string encode = string.Empty;
                switch (cType)
                {
                    case CryptoTextType.Hex:
                        encode = BitConverter.ToString(encryptBytes).Replace("-", "");
                        break;
                    case CryptoTextType.Base64:
                        encode = Convert.ToBase64String(encryptBytes);
                        break;
                    case CryptoTextType.Base62:
                        encode = EncodingExtensions.ToBase62(encryptBytes);
                        break;
                    case CryptoTextType.Base62V2:
                        encode = EncodingExtensions.ToBase62V2(encryptBytes);
                        break;
                    default:
                        encode = Convert.ToBase64String(encryptBytes);
                        break;
                }
                return encode;
            }
            catch (CryptoException)
            {

            }
            return "";
        }


        public static String DecryptByKey(String key, String data,
            CryptoTextType keyType = CryptoTextType.Base64,
            CryptoTextType dataType = CryptoTextType.Base64)
        {
            byte[] bsKey = null;
            switch (keyType)
            {
                case CryptoTextType.Hex:
                    bsKey = Hex.Decode(key);
                    break;
                case CryptoTextType.Base64:
                    bsKey = Convert.FromBase64String(key);
                    break;
                case CryptoTextType.Base62:
                    bsKey = EncodingExtensions.FromBase62(key);
                    break;
                case CryptoTextType.Base62V2:
                    bsKey = EncodingExtensions.FromBase62V2(key);
                    break;
                default:
                    bsKey = Convert.FromBase64String(key);
                    break;
            }

            byte[] bsData = null;
            switch (dataType)
            {
                case CryptoTextType.Hex:
                    bsData = Hex.Decode(data);
                    break;
                case CryptoTextType.Base64:
                    bsData = Convert.FromBase64String(data);
                    break;
                case CryptoTextType.Base62:
                    bsData = EncodingExtensions.FromBase62(data);
                    break;
                case CryptoTextType.Base62V2:
                    bsData = EncodingExtensions.FromBase62V2(data);
                    break;
                default:
                    bsData = Convert.FromBase64String(data);
                    break;
            }

            return DecryptByKey(bsKey, bsData, dataType);
        }

        public static void Test()
        {
            string input = "4e6f77206973207468652074696d6520666f7220616c6c204e6f77206973207468652074696d6520666f7220616c6c20";
            input = Convert.ToBase64String(Encoding.Default.GetBytes(input));
            String key = "";
            BouncyCastleDesEdeUtils.GenerationKey(ref key);

            //String sKey = "ef0d9b7f704ccd5be591945713b51a375d92c7922552e0bc";
            //key = Hex.Decode(sKey);

            Console.WriteLine($"3des key={key}");
            Console.WriteLine($"3des input={input}");

            String en_data = BouncyCastleDesEdeUtils.EncryptByKey(key, input,dataType: CryptoTextType.Base64);
            Console.WriteLine($"3des en={en_data}");
            String de_data = BouncyCastleDesEdeUtils.DecryptByKey(key, en_data,dataType: CryptoTextType.Base64);
            Console.WriteLine($"3des output:{de_data}");
            bool ret = String.Equals(input, de_data, StringComparison.InvariantCultureIgnoreCase);

            Console.WriteLine($"3des equal = {ret}");
        }
    }

public static class EncodingExtensions
    {
        private static string Base62CodingSpace = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        private static char fillChar = '9'; // 填充符

        /// <summary>
        /// Convert a byte array
        /// </summary>
        /// <param name="original">Byte array</param>
        /// <returns>Base62 string</returns>
        public static string ToBase62(this byte[] original)
        {
            StringBuilder sb = new StringBuilder();
            BitStream stream = new BitStream(original);         // Set up the BitStream
            byte[] read = new byte[1];                          // Only read 6-bit at a time
            while (true)
            {
                read[0] = 0;
                int length = stream.Read(read, 0, 6);           // Try to read 6 bits
                if (length == 6)                                // Not reaching the end
                {
                    if ((int)(read[0] >> 3) == 0x1f)            // First 5-bit is 11111
                    {
                        sb.Append(Base62CodingSpace[61]);
                        stream.Seek(-1, SeekOrigin.Current);    // Leave the 6th bit to next group
                    }
                    else if ((int)(read[0] >> 3) == 0x1e)       // First 5-bit is 11110
                    {
                        sb.Append(Base62CodingSpace[60]);
                        stream.Seek(-1, SeekOrigin.Current);
                    }
                    else                                        // Encode 6-bit
                    {
                        sb.Append(Base62CodingSpace[(int)(read[0] >> 2)]);
                    }
                }
                else if (length == 0)                           // Reached the end completely
                {
                    break;
                }
                else                                            // Reached the end with some bits left
                {
                    // Padding 0s to make the last bits to 6 bit
                    sb.Append(Base62CodingSpace[(int)(read[0] >> (int)(8 - length))]);
                    break;
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// Convert a Base62 string to byte array
        /// </summary>
        /// <param name="base62">Base62 string</param>
        /// <returns>Byte array</returns>
        public static byte[] FromBase62(this string base62)
        {
            // Character count
            int count = 0;

            // Set up the BitStream
            BitStream stream = new BitStream(base62.Length * 6 / 8);

            foreach (char c in base62)
            {
                // Look up coding table
                int index = Base62CodingSpace.IndexOf(c);

                // If end is reached
                if (count == base62.Length - 1)
                {
                    // Check if the ending is good
                    int mod = (int)(stream.Position % 8);
                    if (mod == 0)
                    {
                        throw new InvalidDataException("an extra character was found");
                    }

                    // (8 - mod)剩余待写入位数大于6, 说明字节缺失
                    if ((8 - mod) > 6)
                    {
                        throw new InvalidDataException("ending character was lost");
                    }

                    // index位移操作之后大于零, 说明剩余bit空间不足
                    if ((index >> (8 - mod)) > 0)
                    {
                        throw new InvalidDataException("invalid ending character was found");
                    }

                    stream.Write(new byte[] { (byte)(index << mod) }, 0, 8 - mod);
                }
                else
                {
                    // If 60 or 61 then only write 5 bits to the stream, otherwise 6 bits.
                    if (index == 60)
                    {
                        stream.Write(new byte[] { 0xf0 }, 0, 5);
                    }
                    else if (index == 61)
                    {
                        stream.Write(new byte[] { 0xf8 }, 0, 5);
                    }
                    else
                    {
                        stream.Write(new byte[] { (byte)index }, 2, 6);
                    }
                }
                count++;
            }

            // Dump out the bytes
            byte[] result = new byte[stream.Position / 8];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(result, 0, result.Length * 8);
            return result;
        }

        /// <summary>
        /// 新版Base62加密, 4的倍数后面加一个填充符9
        /// </summary>
        /// <param name="original">Byte array</param>
        /// <returns>Base62 string</returns>
        public static string ToBase62V2(this byte[] original)
        {
            string encode = ToBase62(original);
            return (encode.Length % 4 == 0) ? (encode + fillChar) : encode;
        }

        /// <summary>
        /// 新版Base62解密, 4的倍数+1时, 尾部是A尝试解析两次
        /// </summary>
        /// <param name="base62">Base62 string</param>
        /// <returns>Byte array</returns>
        public static byte[] FromBase62V2(this string base62)
        {
            // 最后一位是A
            if ((base62.Length % 4 == 1) && (base62[base62.Length - 1] == fillChar))
            {
                return FromBase62(base62.Substring(0, base62.Length - 1));
            }
            else
            {
                return FromBase62(base62);
            }
        }

        /// <summary>
        /// 解析Base62
        /// </summary>
        /// <param name="base62"></param>
        /// <returns></returns>
        public static byte[] DecodeBase62(this string base62)
        {
            // 1. 去掉填充符解析
            byte[] result = new byte[0];
            if (TryDecode(base62.Substring(0, base62.Length - 1), ref result))
            {
                return result;
            }

            // 2. 解析原字符串
            if (TryDecode(base62, ref result))
            {
                return result;
            }

            return result;
        }

        public static bool TryDecode(this string base62, ref byte[] result)
        {
            // Character count
            int count = 0;

            // Set up the BitStream
            BitStream stream = new BitStream(base62.Length * 6 / 8);

            foreach (char c in base62)
            {
                // Look up coding table
                int index = Base62CodingSpace.IndexOf(c);

                // If end is reached
                if (count == base62.Length - 1)
                {
                    // Check if the ending is good
                    int mod = (int)(stream.Position % 8);
                    if (mod == 0)
                    {
                        // InvalidDataException("an extra character was found");
                        return false;
                    }

                    // (8 - mod)剩余待写入位数大于6, 说明字节缺失
                    if ((8 - mod) > 6)
                    {
                        // InvalidDataException("ending character was lost");
                        return false;
                    }

                    // index位移操作之后大于零, 说明剩余bit空间不足
                    if ((index >> (8 - mod)) > 0)
                    {
                        // InvalidDataException("invalid ending character was found");
                        return false;
                    }

                    stream.Write(new byte[] { (byte)(index << mod) }, 0, 8 - mod);
                }
                else
                {
                    // If 60 or 61 then only write 5 bits to the stream, otherwise 6 bits.
                    if (index == 60)
                    {
                        stream.Write(new byte[] { 0xf0 }, 0, 5);
                    }
                    else if (index == 61)
                    {
                        stream.Write(new byte[] { 0xf8 }, 0, 5);
                    }
                    else
                    {
                        stream.Write(new byte[] { (byte)index }, 2, 6);
                    }
                }
                count++;
            }

            // Dump out the bytes
            result = new byte[stream.Position / 8];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(result, 0, result.Length * 8);
            return true;
        }
    }
/// <summary>
    /// Utility that read and write bits in byte array
    /// </summary>
    public class BitStream : Stream
    {
        private byte[] Source { get; set; }

        /// <summary>
        /// Initialize the stream with capacity
        /// </summary>
        /// <param name="capacity">Capacity of the stream</param>
        public BitStream(int capacity)
        {
            this.Source = new byte[capacity];
        }

        /// <summary>
        /// Initialize the stream with a source byte array
        /// </summary>
        /// <param name="source"></param>
        public BitStream(byte[] source)
        {
            this.Source = source;
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Bit length of the stream
        /// </summary>
        public override long Length
        {
            get { return Source.Length * 8; }
        }

        /// <summary>
        /// Bit position of the stream
        /// </summary>
        public override long Position { get; set; }

        /// <summary>
        /// Read the stream to the buffer
        /// </summary>
        /// <param name="buffer">Buffer</param>
        /// <param name="offset">Offset bit start position of the stream</param>
        /// <param name="count">Number of bits to read</param>
        /// <returns>Number of bits read</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            // Temporary position cursor
            long tempPos = this.Position;
            tempPos += offset;

            // Buffer byte position and in-byte position
            int readPosCount = 0, readPosMod = 0;

            // Stream byte position and in-byte position
            long posCount = tempPos >> 3;
            int posMod = (int)(tempPos - ((tempPos >> 3) << 3));

            while (tempPos < this.Position + offset + count && tempPos < this.Length)
            {
                // Copy the bit from the stream to buffer
                if ((((int)this.Source[posCount]) & (0x1 << (7 - posMod))) != 0)
                {
                    buffer[readPosCount] = (byte)((int)(buffer[readPosCount]) | (0x1 << (7 - readPosMod)));
                }
                else
                {
                    buffer[readPosCount] = (byte)((int)(buffer[readPosCount]) & (0xffffffff - (0x1 << (7 - readPosMod))));
                }

                // Increment position cursors
                tempPos++;
                if (posMod == 7)
                {
                    posMod = 0;
                    posCount++;
                }
                else
                {
                    posMod++;
                }
                if (readPosMod == 7)
                {
                    readPosMod = 0;
                    readPosCount++;
                }
                else
                {
                    readPosMod++;
                }
            }
            int bits = (int)(tempPos - this.Position - offset);
            this.Position = tempPos;
            return bits;
        }

        /// <summary>
        /// Set up the stream position
        /// </summary>
        /// <param name="offset">Position</param>
        /// <param name="origin">Position origin</param>
        /// <returns>Position after setup</returns>
        public override long Seek(long offset, SeekOrigin origin)
        {
            switch (origin)
            {
                case (SeekOrigin.Begin):
                    {
                        this.Position = offset;
                        break;
                    }
                case (SeekOrigin.Current):
                    {
                        this.Position += offset;
                        break;
                    }
                case (SeekOrigin.End):
                    {
                        this.Position = this.Length + offset;
                        break;
                    }
            }
            return this.Position;
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Write from buffer to the stream
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="offset">Offset start bit position of buffer</param>
        /// <param name="count">Number of bits</param>
        public override void Write(byte[] buffer, int offset, int count)
        {
            // Temporary position cursor
            long tempPos = this.Position;

            // Buffer byte position and in-byte position
            int readPosCount = offset >> 3, readPosMod = offset - ((offset >> 3) << 3);

            // Stream byte position and in-byte position
            long posCount = tempPos >> 3;
            int posMod = (int)(tempPos - ((tempPos >> 3) << 3));

            while (tempPos < this.Position + count && tempPos < this.Length)
            {
                // Copy the bit from buffer to the stream
                if ((((int)buffer[readPosCount]) & (0x1 << (7 - readPosMod))) != 0)
                {
                    this.Source[posCount] = (byte)((int)(this.Source[posCount]) | (0x1 << (7 - posMod)));
                }
                else
                {
                    this.Source[posCount] = (byte)((int)(this.Source[posCount]) & (0xffffffff - (0x1 << (7 - posMod))));
                }

                // Increment position cursors
                tempPos++;
                if (posMod == 7)
                {
                    posMod = 0;
                    posCount++;
                }
                else
                {
                    posMod++;
                }
                if (readPosMod == 7)
                {
                    readPosMod = 0;
                    readPosCount++;
                }
                else
                {
                    readPosMod++;
                }
            }
            this.Position = tempPos;
        }
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值