} // DecryptArray

        /*
         * private static bool DONT_USE_AESEncDecArray(bool bEncryptorDecrypt, ref byte[] aData, byte[] aAESKey, byte[] aIV = null)
         * {
         *  bool bRet = true;
         *  try
         *  {
         *      if (   (aData == null)
         || ((bEncryptorDecrypt == true)  && (aData.Length == 0))
         || ((bEncryptorDecrypt == false) && (aData.Length <= 16))   //Must be longer than the IV, when decrypting
         || (aAESKey.Length != 32)
         || ((aIV != null) && (aIV.Length != 16)))
         ||         return false;
         ||
         ||     // Instantiate a new Aes object to perform string symmetric encryption
         ||
         ||     using (Rijndael AES = RijndaelManaged.Create())  //Not FIPS compliant.  :(
         ||     //using (Aes AES = Aes.Create())  //Issues! Not compatible with AES CPP implementation
         ||     {
         ||         //Construct the IV
         ||         bool bIVWasNull = (aIV == null);
         ||         if (bIVWasNull)
         ||             aIV = new byte[16];
         ||
         ||         if (bEncryptorDecrypt)
         ||         {
         ||             if (bIVWasNull)
         ||                 aIV.FillRandom();  //when encrypting: new IV
         ||         }
         ||         else
         ||             Array.Copy(aData, aData.Length - 16, aIV, 0, 16);  //when decrypting: use the IV thats the last 16 bytes of the data.
         ||
         ||         // Set mode, padding, key and IV
         ||         AES.Mode      = CipherMode.CFB;
         ||         AES.Padding   = PaddingMode.None;
         ||         AES.Key       = aAESKey;
         ||         AES.IV        = aIV;
         ||         AES.BlockSize = 128; //16 bytes
         ||
         ||         // Instantiate a new MemoryStream object to contain the encrypted bytes
         ||         MemoryStream ms = new MemoryStream();
         ||         //Dispose not required on MemoryStream, but gives a compiler warning/error when in a 'using' as CryptoStream below disposes of it as well.
         ||         //using (MemoryStream ms = new MemoryStream())
         ||         {
         ||             // Instantiate a new encryptor/decryptor from our Aes object
         ||             using (ICryptoTransform aesCryptor = bEncryptorDecrypt ? AES.CreateEncryptor() : AES.CreateDecryptor())
         ||             {
         ||                 // Instantiate a new CryptoStream object to process the data and write it to the memory stream
         ||                 using (CryptoStream cs = new CryptoStream(ms, aesCryptor, CryptoStreamMode.Write))
         ||                 {
         ||                     // Encrypt/decrypt the input
         ||                     int iCount = bEncryptorDecrypt ? aData.Length : aData.Length - 16;
         ||                     cs.Write(aData, 0, iCount);  //-16, ignore the IV
         ||
         ||                     //Add padding
         ||                     int iPadded = -1;
         ||                     {
         ||                         //Padding.. .Why do we have to do this!
         ||                         int iBlockSizeInBytes = AES.BlockSize / 8;  //Bits to bytes.
         ||
         ||                         int iCompleteBlock = iBlockSizeInBytes - (iCount % iBlockSizeInBytes);
         ||                         if (iCompleteBlock < iBlockSizeInBytes)
         ||                         {
         ||                             iPadded = iCompleteBlock;
         ||                             byte[] aZero = new byte[iPadded];
         ||                             cs.Write(aZero, 0, iPadded);  //-16, ignore the IV
         ||                         }
         ||
         ||                     }
         ||
         ||                     // Complete the encrypt/decrypt process
         ||                     cs.FlushFinalBlock();
         ||
         ||                     //Remove Padding
         ||                     if (iPadded > 0)
         ||                     {
         ||
         ||                         long iLen = ms.Length;
         ||                         if (iLen > iPadded)
         ||                             ms.SetLength(iLen - iPadded);
         ||                     }
         ||
         ||                     if (bEncryptorDecrypt)
         ||                         ms.Write(aIV, 0, aIV.Length);
         ||
         ||                     // Convert the encrypted/decrypted data from a MemoryStream to a byte array
         ||                     aData = ms.ToArray();
         ||                 }
         ||             }
         ||         }
         ||     }
         || }
         || catch (Exception e) { bRet = false;  e.CatchMessage().TraceError("EncDecArray(): "); }
         || return bRet;
         ||} // DONT_USE_AESEncDecArray
         */

        private static bool AESEncDecArray(bool bEncryptorDecrypt, ref byte[] aData, byte[] aAESKey, byte[] aIV = null)
        {
            bool bRet = true;

            try
            {
                if ((aData == null) ||
                    ((bEncryptorDecrypt == true) && (aData.Length == 0)) ||
                    ((bEncryptorDecrypt == false) && (aData.Length <= 16)) ||   //Must be longer than the IV, when decrypting
                    (aAESKey.Length != 32) ||
                    ((aIV != null) && (aIV.Length != 16)))
                {
                    return(false);
                }

                //Construct the IV
                bool bIVWasNull = (aIV == null);
                if (bIVWasNull)
                {
                    aIV = new byte[16];
                }

                int iDataLength = 0;
                if (bEncryptorDecrypt)
                {
                    iDataLength = aData.Length;
                    if (bIVWasNull)
                    {
                        aIV.FillRandom();  //when encrypting: new IV
                    }
                }
                else
                {
                    Array.Copy(aData, aData.Length - 16, aIV, 0, 16);  //when decrypting: use the IV thats the last 16 bytes of the data.
                    iDataLength = aData.Length - 16;
                }

                CfbBlockCipher cfb = new CfbBlockCipher(new AesEngine(), 128);
                cfb.Init(bEncryptorDecrypt, new ParametersWithIV(new KeyParameter(aAESKey), aIV));

                int iBlockSize = cfb.GetBlockSize();
                for (int i = 0; i < iDataLength; i += iBlockSize)
                {
                    int iRet       = 0;
                    int iRemaining = iDataLength - i;
                    if (iRemaining < iBlockSize)
                    {
                        //Last partial block
                        byte[] aIn  = new byte[iBlockSize];
                        byte[] aOut = new byte[iBlockSize];
                        Array.Copy(aData, i, aIn, 0, iRemaining);

                        if (bEncryptorDecrypt)
                        {
                            iRet = cfb.EncryptBlock(aIn, 0, aOut, 0);
                        }
                        else
                        {
                            iRet = cfb.DecryptBlock(aIn, 0, aOut, 0);
                        }
                        Array.Copy(aOut, 0, aData, i, iRemaining);
                        continue;
                    }

                    if (bEncryptorDecrypt)
                    {
                        iRet = cfb.EncryptBlock(aData, i, aData, i);
                    }
                    else
                    {
                        iRet = cfb.DecryptBlock(aData, i, aData, i);
                    }
                }

                if (bEncryptorDecrypt)
                {
                    //Append IV.
                    Array.Resize(ref aData, iDataLength + 16);
                    Array.Copy(aIV, 0, aData, iDataLength, 16);
                }
                else
                {
                    //Remove IV
                    Array.Resize(ref aData, iDataLength);
                }
            }
            catch (Exception e) { bRet = false; e.CatchMessage().TraceError("AESEncDecArray(): "); }
            return(bRet);
        } // AESEncDecArray
예제 #2
0
        public static IBufferedCipher GetCipher(
            string algorithm)
        {
            if (algorithm == null)
            {
                throw new ArgumentNullException("algorithm");
            }

            algorithm = algorithm.ToUpper(CultureInfo.InvariantCulture);

            string aliased = (string)algorithms[algorithm];

            if (aliased != null)
            {
                algorithm = aliased;
            }



            IBasicAgreement iesAgreement = null;

            if (algorithm == "IES")
            {
                iesAgreement = new DHBasicAgreement();
            }
            else if (algorithm == "ECIES")
            {
                iesAgreement = new ECDHBasicAgreement();
            }

            if (iesAgreement != null)
            {
                return(new BufferedIesCipher(
                           new IesEngine(
                               iesAgreement,
                               new Kdf2BytesGenerator(
                                   new Sha1Digest()),
                               new HMac(
                                   new Sha1Digest()))));
            }



            if (algorithm.StartsWith("PBE"))
            {
                if (algorithm.EndsWith("-CBC"))
                {
                    if (algorithm == "PBEWITHSHA1ANDDES-CBC")
                    {
                        return(new PaddedBufferedBlockCipher(
                                   new CbcBlockCipher(new DesEngine())));
                    }
                    else if (algorithm == "PBEWITHSHA1ANDRC2-CBC")
                    {
                        return(new PaddedBufferedBlockCipher(
                                   new CbcBlockCipher(new RC2Engine())));
                    }
                    else if (Strings.IsOneOf(algorithm,
                                             "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"))
                    {
                        return(new PaddedBufferedBlockCipher(
                                   new CbcBlockCipher(new DesEdeEngine())));
                    }
                    else if (Strings.IsOneOf(algorithm,
                                             "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC"))
                    {
                        return(new PaddedBufferedBlockCipher(
                                   new CbcBlockCipher(new RC2Engine())));
                    }
                }
                else if (algorithm.EndsWith("-BC") || algorithm.EndsWith("-OPENSSL"))
                {
                    if (Strings.IsOneOf(algorithm,
                                        "PBEWITHSHAAND128BITAES-CBC-BC",
                                        "PBEWITHSHAAND192BITAES-CBC-BC",
                                        "PBEWITHSHAAND256BITAES-CBC-BC",
                                        "PBEWITHSHA256AND128BITAES-CBC-BC",
                                        "PBEWITHSHA256AND192BITAES-CBC-BC",
                                        "PBEWITHSHA256AND256BITAES-CBC-BC",
                                        "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
                                        "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
                                        "PBEWITHMD5AND256BITAES-CBC-OPENSSL"))
                    {
                        return(new PaddedBufferedBlockCipher(
                                   new CbcBlockCipher(new AesFastEngine())));
                    }
                }
            }



            string[] parts = algorithm.Split('/');

            IBlockCipher           blockCipher     = null;
            IAsymmetricBlockCipher asymBlockCipher = null;
            IStreamCipher          streamCipher    = null;

            string          algorithmName = parts[0];
            CipherAlgorithm cipherAlgorithm;

            try
            {
                cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName);
            }
            catch (ArgumentException)
            {
                throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
            }

            switch (cipherAlgorithm)
            {
            case CipherAlgorithm.AES:
                blockCipher = new AesFastEngine();
                break;

            case CipherAlgorithm.ARC4:
                streamCipher = new RC4Engine();
                break;

            case CipherAlgorithm.BLOWFISH:
                blockCipher = new BlowfishEngine();
                break;

            case CipherAlgorithm.CAMELLIA:
                blockCipher = new CamelliaEngine();
                break;

            case CipherAlgorithm.CAST5:
                blockCipher = new Cast5Engine();
                break;

            case CipherAlgorithm.CAST6:
                blockCipher = new Cast6Engine();
                break;

            case CipherAlgorithm.DES:
                blockCipher = new DesEngine();
                break;

            case CipherAlgorithm.DESEDE:
                blockCipher = new DesEdeEngine();
                break;

            case CipherAlgorithm.ELGAMAL:
                asymBlockCipher = new ElGamalEngine();
                break;

            case CipherAlgorithm.GOST28147:
                blockCipher = new Gost28147Engine();
                break;

            case CipherAlgorithm.HC128:
                streamCipher = new HC128Engine();
                break;

            case CipherAlgorithm.HC256:
                streamCipher = new HC256Engine();
                break;

#if INCLUDE_IDEA
            case CipherAlgorithm.IDEA:
                blockCipher = new IdeaEngine();
                break;
#endif
            case CipherAlgorithm.NOEKEON:
                blockCipher = new NoekeonEngine();
                break;

            case CipherAlgorithm.PBEWITHSHAAND128BITRC4:
            case CipherAlgorithm.PBEWITHSHAAND40BITRC4:
                streamCipher = new RC4Engine();
                break;

            case CipherAlgorithm.RC2:
                blockCipher = new RC2Engine();
                break;

            case CipherAlgorithm.RC5:
                blockCipher = new RC532Engine();
                break;

            case CipherAlgorithm.RC5_64:
                blockCipher = new RC564Engine();
                break;

            case CipherAlgorithm.RC6:
                blockCipher = new RC6Engine();
                break;

            case CipherAlgorithm.RIJNDAEL:
                blockCipher = new RijndaelEngine();
                break;

            case CipherAlgorithm.RSA:
                asymBlockCipher = new RsaBlindedEngine();
                break;

            case CipherAlgorithm.SALSA20:
                streamCipher = new Salsa20Engine();
                break;

            case CipherAlgorithm.SEED:
                blockCipher = new SeedEngine();
                break;

            case CipherAlgorithm.SERPENT:
                blockCipher = new SerpentEngine();
                break;

            case CipherAlgorithm.SKIPJACK:
                blockCipher = new SkipjackEngine();
                break;

            case CipherAlgorithm.TEA:
                blockCipher = new TeaEngine();
                break;

            case CipherAlgorithm.TWOFISH:
                blockCipher = new TwofishEngine();
                break;

            case CipherAlgorithm.VMPC:
                streamCipher = new VmpcEngine();
                break;

            case CipherAlgorithm.VMPC_KSA3:
                streamCipher = new VmpcKsa3Engine();
                break;

            case CipherAlgorithm.XTEA:
                blockCipher = new XteaEngine();
                break;

            default:
                throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
            }

            if (streamCipher != null)
            {
                if (parts.Length > 1)
                {
                    throw new ArgumentException("Modes and paddings not used for stream ciphers");
                }

                return(new BufferedStreamCipher(streamCipher));
            }


            bool cts    = false;
            bool padded = true;
            IBlockCipherPadding padding         = null;
            IAeadBlockCipher    aeadBlockCipher = null;

            if (parts.Length > 2)
            {
                if (streamCipher != null)
                {
                    throw new ArgumentException("Paddings not used for stream ciphers");
                }

                string paddingName = parts[2];

                CipherPadding cipherPadding;
                if (paddingName == "")
                {
                    cipherPadding = CipherPadding.RAW;
                }
                else if (paddingName == "X9.23PADDING")
                {
                    cipherPadding = CipherPadding.X923PADDING;
                }
                else
                {
                    try
                    {
                        cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName);
                    }
                    catch (ArgumentException)
                    {
                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
                    }
                }

                switch (cipherPadding)
                {
                case CipherPadding.NOPADDING:
                    padded = false;
                    break;

                case CipherPadding.RAW:
                    break;

                case CipherPadding.ISO10126PADDING:
                case CipherPadding.ISO10126D2PADDING:
                case CipherPadding.ISO10126_2PADDING:
                    padding = new ISO10126d2Padding();
                    break;

                case CipherPadding.ISO7816_4PADDING:
                case CipherPadding.ISO9797_1PADDING:
                    padding = new ISO7816d4Padding();
                    break;

                case CipherPadding.ISO9796_1:
                case CipherPadding.ISO9796_1PADDING:
                    asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher);
                    break;

                case CipherPadding.OAEP:
                case CipherPadding.OAEPPADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher);
                    break;

                case CipherPadding.OAEPWITHMD5ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest());
                    break;

                case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING:
                case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest());
                    break;

                case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING:
                case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest());
                    break;

                case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING:
                case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest());
                    break;

                case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING:
                case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest());
                    break;

                case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING:
                case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING:
                    asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest());
                    break;

                case CipherPadding.PKCS1:
                case CipherPadding.PKCS1PADDING:
                    asymBlockCipher = new Pkcs1Encoding(asymBlockCipher);
                    break;

                case CipherPadding.PKCS5:
                case CipherPadding.PKCS5PADDING:
                case CipherPadding.PKCS7:
                case CipherPadding.PKCS7PADDING:
                    padding = new Pkcs7Padding();
                    break;

                case CipherPadding.TBCPADDING:
                    padding = new TbcPadding();
                    break;

                case CipherPadding.WITHCTS:
                    cts = true;
                    break;

                case CipherPadding.X923PADDING:
                    padding = new X923Padding();
                    break;

                case CipherPadding.ZEROBYTEPADDING:
                    padding = new ZeroBytePadding();
                    break;

                default:
                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
                }
            }

            string mode = "";
            if (parts.Length > 1)
            {
                mode = parts[1];

                int    di       = GetDigitIndex(mode);
                string modeName = di >= 0 ? mode.Substring(0, di) : mode;

                try
                {
                    CipherMode cipherMode = modeName == ""
                                                ? CipherMode.NONE
                                                : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName);

                    switch (cipherMode)
                    {
                    case CipherMode.ECB:
                    case CipherMode.NONE:
                        break;

                    case CipherMode.CBC:
                        blockCipher = new CbcBlockCipher(blockCipher);
                        break;

                    case CipherMode.CCM:
                        aeadBlockCipher = new CcmBlockCipher(blockCipher);
                        break;

                    case CipherMode.CFB:
                    {
                        int bits = (di < 0)
                                                                ?       8 * blockCipher.GetBlockSize()
                                                                :       int.Parse(mode.Substring(di));

                        blockCipher = new CfbBlockCipher(blockCipher, bits);
                        break;
                    }

                    case CipherMode.CFBDCP:
                    {
                        int bits = (di < 0)
                                ? 8 * blockCipher.GetBlockSize()
                                : int.Parse(mode.Substring(di));

                        blockCipher = new CfbDCPCipher(blockCipher, bits);
                        break;
                    }

                    case CipherMode.CTR:
                        blockCipher = new SicBlockCipher(blockCipher);
                        break;

                    case CipherMode.CTS:
                        cts         = true;
                        blockCipher = new CbcBlockCipher(blockCipher);
                        break;

                    case CipherMode.EAX:
                        aeadBlockCipher = new EaxBlockCipher(blockCipher);
                        break;

                    case CipherMode.GCM:
                        aeadBlockCipher = new GcmBlockCipher(blockCipher);
                        break;

                    case CipherMode.GOFB:
                        blockCipher = new GOfbBlockCipher(blockCipher);
                        break;

                    case CipherMode.OFB:
                    {
                        int bits = (di < 0)
                                                                ?       8 * blockCipher.GetBlockSize()
                                                                :       int.Parse(mode.Substring(di));

                        blockCipher = new OfbBlockCipher(blockCipher, bits);
                        break;
                    }

                    case CipherMode.OPENPGPCFB:
                        blockCipher = new OpenPgpCfbBlockCipher(blockCipher);
                        break;

                    case CipherMode.SIC:
                        if (blockCipher.GetBlockSize() < 16)
                        {
                            throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
                        }
                        blockCipher = new SicBlockCipher(blockCipher);
                        break;

                    default:
                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
                    }
                }
                catch (ArgumentException)
                {
                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
                }
            }

            if (aeadBlockCipher != null)
            {
                if (cts)
                {
                    throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers.");
                }
                if (padded && parts.Length > 2 && parts[2] != "")
                {
                    throw new SecurityUtilityException("Bad padding specified for AEAD cipher.");
                }

                return(new BufferedAeadBlockCipher(aeadBlockCipher));
            }

            if (blockCipher != null)
            {
                if (cts)
                {
                    return(new CtsBlockCipher(blockCipher));
                }

                if (padding != null)
                {
                    return(new PaddedBufferedBlockCipher(blockCipher, padding));
                }

                if (!padded || blockCipher.IsPartialBlockOkay)
                {
                    return(new BufferedBlockCipher(blockCipher));
                }

                return(new PaddedBufferedBlockCipher(blockCipher));
            }

            if (asymBlockCipher != null)
            {
                return(new BufferedAsymmetricBlockCipher(asymBlockCipher));
            }

            throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
        }