Ahmad Yassin
Ahmad Yassin

Reputation: 1

Multiple Encryption with Bouncycastle

Is it possible to encrypt data with multiple encryption algorithms using the BouncyCastle open source library? I have written the code below to pass the output from one cipher as input to the other cipher but I am always getting the same output bytes.

Thanks in advance, Ahmad Yassin

Boolean ProcessFile(
        PaddedBufferedBlockCipher aesCipher,
        PaddedBufferedBlockCipher serpentCipher,
        PaddedBufferedBlockCipher twofishCipher,
        FileStream fin,
        FileStream fout,
        int addOnLength)
    {
        int inputSize = aesCipher.GetBlockSize();
        int outputSize = aesCipher.GetOutputSize(inputSize);

        byte[] inputBuffer = new byte[inputSize];
        byte[] outBuffer = new byte[outputSize];

        long fileLenght = fin.Length - addOnLength;
        long progressStep = fileLenght >= 100 ? fileLenght / 100 : fileLenght;

        long totalLength = 0;
        int inLength = 0;
        int outLength;

        try
        {
            while ((inLength = fin.Read(inputBuffer, 0, inputSize)) != 0)
            {
                outLength = aesCipher.ProcessBytes(inputBuffer, 0, inLength, outBuffer, 0);
                outLength = serpentCipher.ProcessBytes(outBuffer, 0, outLength, outBuffer, 0);
                outLength = twofishCipher.ProcessBytes(outBuffer, 0, outLength, outBuffer, 0);

                fout.Write(outBuffer, 0, outLength);
                totalLength += inLength;
                if (totalLength >= progressStep)
                {
                    DoProgressChanged();
                    totalLength = totalLength % progressStep;
                }
            }
            outLength = aesCipher.DoFinal(outBuffer, 0);
            fout.Write(outBuffer, 0, outLength);
            fout.Close();
            fin.Close();
            return true;
        }
        catch (IOException e)
        {
            throw new IOException(e.Message);
        }
    }


    public event EventHandler ProgressChanged;
    private void DoProgressChanged()
    {
        if (this.ProgressChanged != null)
            this.ProgressChanged(this, new EventArgs());
    }



    enum Mode { Encription = 1, Decription = 0 }
    enum Algorithm { AES = 1, Serpent = 2, Twofish = 3 }
    PaddedBufferedBlockCipher GetCipher(Algorithm algorithm, Mode mode, byte[] key, byte[] iv)
    {
        IBlockCipher blockCipher;
        ICipherParameters parameters = new ParametersWithIV(new KeyParameter(key), iv);
        switch (algorithm)
        {
            case Algorithm.AES:
                blockCipher = new AesFastEngine();
                break;
            case Algorithm.Serpent:
                blockCipher = new SerpentEngine();
                break;
            case Algorithm.Twofish:
                blockCipher = new TwofishEngine();
                break;
            default:
                blockCipher = new AesFastEngine();
                break;
        }
        IBlockCipher cbcblockCipher = new CbcBlockCipher(blockCipher);
        PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(cbcblockCipher, new Pkcs7Padding());
        cipher.Init(mode == Mode.Encription, parameters);
        return cipher;
    }

Upvotes: 0

Views: 614

Answers (1)

Maarten Bodewes
Maarten Bodewes

Reputation: 94078

Of course it is possible, but I would strongly suggest you use some kind of connected streams, or perform three passes over the buffer (first AES, then Serpent, then TwoFish or any other order). Don't perform a block size encryption for every cipher as you do now, as block sizes and other parameters may differ.

Of course, the usefulness of using three separate encryption algorithms is debatable.

Upvotes: 1

Related Questions