Exemplo n.º 1
0
        public virtual void Init(
            bool forEncryption,
            ICipherParameters parameters)
        {
            this.forEncryption = forEncryption;

            KeyParameter keyParam;

            if (parameters is AeadParameters)
            {
                AeadParameters param = (AeadParameters)parameters;

                nonce = param.GetNonce();
                initialAssociatedText = param.GetAssociatedText();

                keyParam = param.Key;
            }
            else if (parameters is ParametersWithIV)
            {
                ParametersWithIV param = (ParametersWithIV)parameters;

                nonce = param.GetIV();
                initialAssociatedText = null;
                keyParam = (KeyParameter)param.Parameters;
            }
            else
            {
                throw new ArgumentException("invalid parameters passed to ChaCha20Poly1305");
            }

            if (nonce == null || nonce.Length < 1)
            {
                throw new ArgumentException("IV must be at least 1 byte");
            }

            //  Geneate the key
            ChaChaX tmpCypher = new ChaChaX();

            byte[]           zero    = new byte[32];
            byte[]           polyKey = new byte[32];
            ParametersWithIV tmpKey  = new ParametersWithIV(keyParam, nonce);

            tmpCypher.Init(true, tmpKey);
            tmpCypher.ProcessBytes(zero, 0, zero.Length, polyKey, 0);

            poly = new Poly1305();

            KeyParameter tmpKey2 = new KeyParameter(polyKey);

            poly.Init(tmpKey2);

            chacha20 = new ChaChaX();
            chacha20.Init(forEncryption, tmpKey);

            InitCipher();
        }
Exemplo n.º 2
0
        public int DoFinal(byte[] output, int outOff)
        {
            byte[] zeros;

            if (data.Length + aadLength == 0)
            {
                InitCipher();
            }

            int extra = (int)data.Length;

            if (forEncryption)
            {
                // Check.OutputLength(output, outOff, bufOff, extra + macSize, "Output buffer too short");
            }
            else
            {
                if (extra < macSize)
                {
                    throw new InvalidCipherTextException("data too short");
                }

                extra -= macSize;

                // Check.OutputLength(output, outOff, extra, "Output buffer too short");
            }

            //  Pad out the AD

            zeros = new byte[16 - (aadLength % 16)];
            if (zeros.Length != 16)
            {
                poly.BlockUpdate(zeros, 0, zeros.Length);
            }

            chacha20.ProcessBytes(data.GetBuffer(), 0, extra, output, outOff);

            if (forEncryption)
            {
                poly.BlockUpdate(output, outOff, extra);
            }
            else
            {
                poly.BlockUpdate(data.GetBuffer(), 0, extra);
            }

            int resultLen = 0;

            zeros = new byte[16 - (extra % 16)];
            if (zeros.Length != 16)
            {
                poly.BlockUpdate(zeros, 0, zeros.Length);
            }

            byte[] lengths = BitConverter.GetBytes((Int64)aadLength);
            poly.BlockUpdate(lengths, 0, lengths.Length);
            lengths = BitConverter.GetBytes((Int64)extra);
            poly.BlockUpdate(lengths, 0, lengths.Length);

            macResult = new byte[macSize];
            if (poly.DoFinal(macResult, 0) != macResult.Length)
            {
                throw new Exception("Internal Error");
            }

            if (forEncryption)
            {
                resultLen = extra + macSize;
                Array.Copy(macResult, 0, output, extra + outOff, macSize);
            }
            else
            {
                bool f = true;
                for (int i = 0; i < macSize; i++)
                {
                    f &= (macResult[i] == data.GetBuffer()[extra + i]);
                }
                if (!f)
                {
                    throw new Exception("Authentication Failed");
                }
                resultLen = extra;
            }

            Reset(false);

            return(resultLen);
        }