public static int Encrypt(byte[] plaintext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer) { lock (mutex) { if (cipher == null) { cipher = new ChaCha7539Engine(); } else { cipher.Reset(); } if (_encryptKey == null) { _encryptKey = new KeyParameter(key); } else { _encryptKey.Reset(); _encryptKey.SetKey(key); } if (_temp_Params == null) { _temp_Params = new ParametersWithIV(_encryptKey, nonce); } else { _temp_Params.Reset(); _temp_Params.Set(_encryptKey, nonce); } cipher.Init(true, _temp_Params); byte[] firstBlock = BufferPool.GetBuffer(64); KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock); cipher.ProcessBytes(plaintext, offset, len, outBuffer, 0); byte[] mac = BufferPool.GetBuffer(16); int macsize = CalculateRecordMac(macKey, additionalData, outBuffer, 0, len, mac); Array.Copy(mac, 0, outBuffer, len, macsize); BufferPool.ReturnBuffer(mac); BufferPool.ReturnBuffer(firstBlock); return(len + 16); } }
public static int Decrypt(byte[] ciphertext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer) { var cipher = new ChaCha7539Engine(); var decryptKey = new KeyParameter(key); cipher.Init(false, new ParametersWithIV(decryptKey, nonce)); byte[] firstBlock = BufferPool.GetBuffer(64); KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock); int plaintextLength = len - 16; byte[] calculatedMac = BufferPool.GetBuffer(16); CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength, calculatedMac); byte[] receivedMac = BufferPool.GetBuffer(16); Array.Copy(ciphertext, offset + plaintextLength, receivedMac, 0, receivedMac.Length); if (!Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac)) { BufferPool.ReturnBuffer(calculatedMac); BufferPool.ReturnBuffer(receivedMac); BufferPool.ReturnBuffer(firstBlock); throw new TlsFatalAlert(AlertDescription.bad_record_mac); } BufferPool.ReturnBuffer(calculatedMac); BufferPool.ReturnBuffer(receivedMac); BufferPool.ReturnBuffer(firstBlock); cipher.ProcessBytes(ciphertext, offset, plaintextLength, outBuffer, 0); return(plaintextLength); }
/// <summary> /// Encrypt data with ChaCha20 RFC 7539 /// </summary> /// <param name="input">Input stream to encrypt</param> /// <param name="output">Output stream</param> /// <param name="key">Key</param> /// <param name="nonce">Nonce</param> /// <param name="notifyProgression">Notify progression method</param> /// <param name="bufferSize">Buffer size</param> public static void Encrypt(Stream input, Stream output, byte[] key, byte[] nonce, Action <int> notifyProgression = null, int bufferSize = 4096) { ChaCha7539Engine engine = new ChaCha7539Engine(); ParametersWithIV parameters = new ParametersWithIV(new KeyParameter(key, 0, key.Length), nonce, 0, nonce.Length); engine.Init(true, parameters); int bytesRead; byte[] buffer = new byte[bufferSize]; byte[] enc = new byte[bufferSize]; do { bytesRead = input.Read(buffer, 0, bufferSize); if (bytesRead > 0) { engine.ProcessBytes(buffer, 0, bytesRead, enc, 0); output.Write(enc, 0, bytesRead); if (notifyProgression != null) { notifyProgression(bytesRead); } } } while (bytesRead == bufferSize); }
static bool crypto_aead_chacha20poly1305_ietf_decrypt_detached(Memory <byte> m, ReadOnlyMemory <byte> c, ReadOnlyMemory <byte> mac, ReadOnlyMemory <byte> ad, ReadOnlyMemory <byte> npub, ReadOnlyMemory <byte> k) { var kk = k._AsSegment(); var nn = npub._AsSegment(); var cc = c._AsSegment(); var aa = ad._AsSegment(); var mm = m._AsSegment(); byte[] block0 = new byte[64]; ChaCha7539Engine ctx = new ChaCha7539Engine(); ctx.Init(true, new ParametersWithIV(new KeyParameter(kk.Array, kk.Offset, kk.Count), nn.Array, nn.Offset, nn.Count)); ctx.ProcessBytes(block0, 0, block0.Length, block0, 0); Poly1305 state = new Poly1305(); state.Init(new KeyParameter(block0, 0, AeadChaCha20Poly1305KeySize)); state.BlockUpdate(aa.Array, aa.Offset, aa.Count); if ((aa.Count % 16) != 0) { state.BlockUpdate(zero15, 0, 16 - (aa.Count % 16)); } state.BlockUpdate(cc.Array, cc.Offset, cc.Count); if ((cc.Count % 16) != 0) { state.BlockUpdate(zero15, 0, 16 - (cc.Count % 16)); } byte[] slen = BitConverter.GetBytes((ulong)aa.Count); if (Env.IsBigEndian) { Array.Reverse(slen); } state.BlockUpdate(slen, 0, slen.Length); byte[] mlen = BitConverter.GetBytes((ulong)cc.Count); if (Env.IsBigEndian) { Array.Reverse(mlen); } state.BlockUpdate(mlen, 0, mlen.Length); byte[] computed_mac = new byte[AeadChaCha20Poly1305MacSize]; state.DoFinal(computed_mac, 0); if (computed_mac.AsSpan().SequenceEqual(mac.Span) == false) { return(false); } ctx.ProcessBytes(cc.Array, cc.Offset, cc.Count, mm.Array, mm.Offset); return(true); }
/// <summary> /// Decrypt data with ChaCha20 RFC 7539 /// </summary> /// <param name="data">Data to decrypt</param> /// <param name="key">Key</param> /// <param name="nonce">Nonce</param> /// <returns>Decrypted data</returns> public static byte[] Decrypt(byte[] data, byte[] key, byte[] nonce) { byte[] dec = new byte[data.Length]; ChaCha7539Engine engine = new ChaCha7539Engine(); ParametersWithIV parameters = new ParametersWithIV(new KeyParameter(key, 0, key.Length), nonce, 0, nonce.Length); engine.Init(false, parameters); engine.ProcessBytes(data, 0, data.Length, dec, 0); return(dec); }
public static byte[] ChaCha20Encrypt(byte[] plainText, byte[] key, byte[] nonce, bool skipFirst64Byte = false) { var engine = new ChaCha7539Engine(); engine.Init(true, new ParametersWithIV(new KeyParameter(key), nonce)); var cipherText = new byte[plainText.Length]; if (skipFirst64Byte) { engine.ProcessBytes(new byte[64], 0, 64, new byte[64], 0); } engine.ProcessBytes(plainText, 0, plainText.Length, cipherText, 0); return(cipherText); }
private byte[] EncryptOrDecrypt(bool isEncrypt, byte[] input, byte[] key, byte[] nonce, bool skip1Block) { var eng = new ChaCha7539Engine(); var keyParam = new ParametersWithIV(new KeyParameter(key), nonce); eng.Init(isEncrypt, keyParam); var output = new byte[input.Length]; if (skip1Block) { var dummy = new byte[64]; eng.ProcessBytes(new byte[64], 0, 64, dummy, 0); } eng.ProcessBytes(input, 0, input.Length, output, 0); return(output); }
public static int Encrypt(byte[] plaintext, int offset, int len, byte[] additionalData, byte[] nonce, byte[] key, byte[] outBuffer) { var cipher = new ChaCha7539Engine(); var encryptKey = new KeyParameter(key); cipher.Init(true, new ParametersWithIV(encryptKey, nonce)); byte[] firstBlock = BufferPool.GetBuffer(64); KeyParameter macKey = GenerateRecordMacKey(cipher, firstBlock); cipher.ProcessBytes(plaintext, offset, len, outBuffer, 0); byte[] mac = BufferPool.GetBuffer(16); int macsize = CalculateRecordMac(macKey, additionalData, outBuffer, 0, len, mac); Array.Copy(mac, 0, outBuffer, len, macsize); BufferPool.ReturnBuffer(mac); BufferPool.ReturnBuffer(firstBlock); return(len + 16); }
public virtual void Init(bool forEncryption, ICipherParameters parameters) { KeyParameter initKeyParam; byte[] initNonce; ICipherParameters chacha20Params; if (parameters is AeadParameters) { AeadParameters aeadParams = (AeadParameters)parameters; int macSizeBits = aeadParams.MacSize; if ((MacSize * 8) != macSizeBits) { throw new ArgumentException("Invalid value for MAC size: " + macSizeBits); } initKeyParam = aeadParams.Key; initNonce = aeadParams.GetNonce(); chacha20Params = new ParametersWithIV(initKeyParam, initNonce); this.mInitialAad = aeadParams.GetAssociatedText(); } else if (parameters is ParametersWithIV) { ParametersWithIV ivParams = (ParametersWithIV)parameters; initKeyParam = (KeyParameter)ivParams.Parameters; initNonce = ivParams.GetIV(); chacha20Params = ivParams; this.mInitialAad = null; } else { throw new ArgumentException("invalid parameters passed to ChaCha20Poly1305", "parameters"); } // Validate key if (null == initKeyParam) { if (State.Uninitialized == mState) { throw new ArgumentException("Key must be specified in initial init"); } } else { if (KeySize != initKeyParam.GetKey().Length) { throw new ArgumentException("Key must be 256 bits"); } } // Validate nonce if (null == initNonce || NonceSize != initNonce.Length) { throw new ArgumentException("Nonce must be 96 bits"); } // Check for encryption with reused nonce if (State.Uninitialized != mState && forEncryption && Arrays.AreEqual(mNonce, initNonce)) { if (null == initKeyParam || Arrays.AreEqual(mKey, initKeyParam.GetKey())) { throw new ArgumentException("cannot reuse nonce for ChaCha20Poly1305 encryption"); } } if (null != initKeyParam) { Array.Copy(initKeyParam.GetKey(), 0, mKey, 0, KeySize); } Array.Copy(initNonce, 0, mNonce, 0, NonceSize); mChacha20.Init(true, chacha20Params); this.mState = forEncryption ? State.EncInit : State.DecInit; Reset(true, false); }