public void Encrypt(ReadOnlySpan <byte> nonce, ReadOnlySpan <byte> source, Span <byte> destination, Span <byte> tag, ReadOnlySpan <byte> associatedData = default) { var input = ArrayPool <byte> .Shared.Rent(source.Length); var output = ArrayPool <byte> .Shared.Rent(destination.Length + tag.Length); try { _engine = new BufferedAeadBlockCipher(new GcmBlockCipher(_aes)); _engine.Init(true, new AeadParameters(_key, 128, nonce.ToArray(), associatedData.ToArray())); source.CopyTo(input); _engine.DoFinal(input, 0, source.Length, output, 0); output.AsSpan(0, destination.Length).CopyTo(destination); output.AsSpan(destination.Length, tag.Length).CopyTo(tag); } finally { ArrayPool <byte> .Shared.Return(input); ArrayPool <byte> .Shared.Return(output); } }
public BcAesGcmCrypto(byte[] key) { _aes = new AesFastEngine(); _key = new KeyParameter(key); _engine = new BufferedAeadBlockCipher(new GcmBlockCipher(_aes)); }
/// <summary> /// Create a buffered cipher to encrypt or decrypt a stream as it is being read /// </summary> /// <param name="forEncryption">forEncryption if true the cipher is initialised for encryption, if false for decryption</param> /// <param name="key">Key to be used for encryption</param> /// <param name="nonce">Nonce to be used for encryption</param> /// <param name="tagSize">Tag size in bits for the tag appended in the end of the stream</param> /// <param name="associatedText">Additional associated data</param> /// <returns></returns> internal static IBufferedCipher CreateCipher(bool forEncryption, byte[] key, int tagSize, byte[] nonce, byte[] associatedText) { var aesEngine = new AesEngine(); var blockCipher = new GcmBlockCipher(aesEngine); var aeadBlockCipher = new BufferedAeadBlockCipher(blockCipher); var parameters = new AeadParameters(new KeyParameter(key), tagSize, nonce, associatedText); aeadBlockCipher.Init(forEncryption, parameters); return(aeadBlockCipher); }
/// <summary> /// Generate cipher. The cipher can be reused. Except GCM cipher mode. /// </summary> /// <param name="forEncryption"></param> /// <param name="mode">Symmetric algorithm cipher mode.</param> /// <param name="padding">Symmetric algorithm padding mode.</param> /// <param name="parameters">Parameters.</param> /// <returns></returns> /// <exception cref="Exception"/> public IBufferedCipher GenerateCipher(bool forEncryption, SymmetricCipherMode mode, SymmetricPaddingMode padding, ICipherParameters parameters) { IBlockCipherPadding pad; switch (padding) { case SymmetricPaddingMode.NoPadding: pad = null; break; case SymmetricPaddingMode.PKCS7: pad = Common.PKCS7Padding; break; case SymmetricPaddingMode.Zeros: pad = Common.ZEROBYTEPadding; break; case SymmetricPaddingMode.X923: pad = Common.X923Padding; break; case SymmetricPaddingMode.ISO10126: pad = Common.ISO10126d2Padding; break; case SymmetricPaddingMode.ISO7816_4: pad = Common.ISO7816d4Padding; break; case SymmetricPaddingMode.TBC: pad = Common.TBCPadding; break; default: throw new CryptographicException("Unsupported padding mode."); } IBlockCipher engine = GenerateEngine(); IBufferedCipher cipher; switch (mode) { case SymmetricCipherMode.CBC: cipher = pad is null ? new BufferedBlockCipher(new CbcBlockCipher(engine)) : new PaddedBufferedBlockCipher(new CbcBlockCipher(engine), pad); break; case SymmetricCipherMode.ECB: cipher = pad is null ? new BufferedBlockCipher(engine) : new PaddedBufferedBlockCipher(engine, pad); break; case SymmetricCipherMode.OFB: int ofbs = ((ParametersWithIV)parameters).GetIV().Length * 8; cipher = pad is null ? new BufferedBlockCipher(new OfbBlockCipher(engine, ofbs)) : new PaddedBufferedBlockCipher(new OfbBlockCipher(engine, ofbs), pad); break; case SymmetricCipherMode.CFB: int cfbs = ((ParametersWithIV)parameters).GetIV().Length * 8; cipher = pad is null ? new BufferedBlockCipher(new CfbBlockCipher(engine, cfbs)) : new PaddedBufferedBlockCipher(new CfbBlockCipher(engine, cfbs), pad); break; case SymmetricCipherMode.CTS: if (pad is null) { cipher = new CtsBlockCipher(new CbcBlockCipher(engine)); break; } throw new CryptographicException("CTS cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); case SymmetricCipherMode.CTR: cipher = pad is null ? new BufferedBlockCipher(new SicBlockCipher(engine)) : new PaddedBufferedBlockCipher(new SicBlockCipher(engine), pad); break; case SymmetricCipherMode.CTS_ECB: if (pad is null) { cipher = new CtsBlockCipher(engine); break; } throw new CryptographicException("CTS cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); case SymmetricCipherMode.GOFB: if (this.BlockSize == 64) { cipher = pad is null ? new BufferedBlockCipher(new GOfbBlockCipher(engine)) : new PaddedBufferedBlockCipher(new GOfbBlockCipher(engine), pad); break; } throw new CryptographicException("GOFB cipher mode uses with a block size of 64 bits algorithm (e.g. DESede)."); case SymmetricCipherMode.OpenPGPCFB: cipher = pad is null ? new BufferedBlockCipher(new OpenPgpCfbBlockCipher(engine)) : new PaddedBufferedBlockCipher(new OpenPgpCfbBlockCipher(engine), pad); break; case SymmetricCipherMode.SIC: if (this.BlockSize >= 128) { cipher = pad is null ? new BufferedBlockCipher(new SicBlockCipher(engine)) : new PaddedBufferedBlockCipher(new SicBlockCipher(engine), pad); break; } throw new CryptographicException("SIC cipher mode uses with a block size of at least 128 bits algorithm (e.g. AES)."); case SymmetricCipherMode.CCM: if (pad is null) { if (this.BlockSize == 128) { cipher = new BufferedAeadBlockCipher(new CcmBlockCipher(engine)); break; } throw new CryptographicException("CCM cipher mode uses with a block size of 128 bits algorithm (e.g. AES)."); } throw new CryptographicException("CCM cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); case SymmetricCipherMode.EAX: if (pad is null) { if (this.BlockSize == 64 || this.BlockSize == 128) { cipher = new BufferedAeadBlockCipher(new EaxBlockCipher(engine)); break; } throw new CryptographicException("EAX cipher mode uses with a block size of 64 or 128 bits algorithm (e.g. DESede, AES)."); } throw new CryptographicException("EAX cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); case SymmetricCipherMode.GCM: if (pad is null) { if (this.BlockSize == 128) { cipher = new BufferedAeadBlockCipher(new GcmBlockCipher(engine)); break; } throw new CryptographicException("GCM cipher mode uses with a block size of 128 bits algorithm (e.g. AES)."); } throw new CryptographicException("GCM cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); case SymmetricCipherMode.OCB: if (pad is null) { if (this.BlockSize == 128) { cipher = new BufferedAeadBlockCipher(new OcbBlockCipher(engine, GenerateEngine())); break; } throw new CryptographicException("OCB cipher mode uses with a block size of 128 bits algorithm (e.g. AES)."); } throw new CryptographicException("OCB cipher mode can only select SymmetricPaddingMode.NoPadding padding mode."); default: throw new CryptographicException("Unsupported cipher mode."); } cipher.Init(forEncryption, parameters); return(cipher); }