public virtual void Init(
            bool forEncryption,
            ICipherParameters parameters)
        {
            _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
            ChaCha7539Engine tmpCypher = new ChaCha7539Engine();

            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();
        }
Exemple #2
0
        public byte[] Decrypt(byte[] cipher, byte[] key, byte[] iv, byte[] aad = null, byte[] associated = null)
        {
            if (key.Length * 8 != this.KeySize)
            {
                throw new InvalidOperationException($"the given key has invalid size {key.Length * 8}, expect {this.KeySize}");
            }
            if (iv.Length != 12)
            {
                throw new InvalidOperationException($"chacha20 requires 96 bits IV, got {iv.Length * 8}");
            }
            if (cipher.Length <= 16)
            {
                throw new ArgumentException($"incorrect argument [cipher] size");
            }
            // split cipher and mac
            var cipherText = cipher.Take(cipher.Length - 16).ToArray();
            var macText    = cipher.Skip(cipher.Length - 16).ToArray();

            var engine = new Engines.ChaCha7539Engine();

            engine.Init(false, new Parameters.ParametersWithIV(new Parameters.KeyParameter(key), iv));
            // calculate mac key
            var mackeyBlock = new byte[64];

            engine.ProcessBytes(mackeyBlock, 0, mackeyBlock.Length, mackeyBlock, 0);
            var mackey = mackeyBlock.Take(32).ToArray();
            // calculate mac
            var poly = new Macs.Poly1305();

            poly.Init(new Parameters.KeyParameter(mackey));
            PolyUpdateMacText(poly, aad);
            PolyUpdateMacText(poly, cipherText);
            PolyUpdateMacLength(poly, aad.Length);
            PolyUpdateMacLength(poly, cipherText.Length);
            var myMac = PolyDoFinal(poly);

            if (!Utils.BytesEqual(myMac, macText))
            {
                throw new ArgumentException("bad record mac");
            }
            // decrypt
            var plain = new byte[cipherText.Length];

            engine.ProcessBytes(cipherText, 0, cipherText.Length, plain, 0);
            return(plain);
        }
Exemple #3
0
        public byte[] Encrypt(byte[] plain, byte[] key, byte[] iv, byte[] aad = null, byte[] associated = null)
        {
            if (key.Length * 8 != this.KeySize)
            {
                throw new InvalidOperationException($"the given key has invalid size {key.Length * 8}, expect {this.KeySize}");
            }
            if (iv.Length != 12)
            {
                throw new InvalidOperationException($"chacha20 requires 96 bits IV, got {iv.Length * 8}");
            }

            var engine = new Engines.ChaCha7539Engine();

            engine.Init(true, new Parameters.ParametersWithIV(new Parameters.KeyParameter(key), iv));
            // calculate mac key
            var mackeyBlock = new byte[64];

            engine.ProcessBytes(mackeyBlock, 0, mackeyBlock.Length, mackeyBlock, 0);
            var mackey = mackeyBlock.Take(32).ToArray();
            // encrypt
            var cipher = new byte[plain.Length];

            engine.ProcessBytes(plain, 0, plain.Length, cipher, 0);
            // calculate mac
            var poly = new Macs.Poly1305();

            poly.Init(new Parameters.KeyParameter(mackey));
            PolyUpdateMacText(poly, aad);
            PolyUpdateMacText(poly, cipher);
            PolyUpdateMacLength(poly, aad.Length);
            PolyUpdateMacLength(poly, cipher.Length);
            var myMac       = PolyDoFinal(poly);
            var cipherBlock = new byte[cipher.Length + myMac.Length];

            Buffer.BlockCopy(cipher, 0, cipherBlock, 0, cipher.Length);
            Buffer.BlockCopy(myMac, 0, cipherBlock, cipher.Length, myMac.Length);
            return(cipherBlock);
        }