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(); }
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); }