/// <inheritdoc /> public override unsafe byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { switch (this.baseKey.Padding) { case SymmetricAlgorithmPadding.None: Requires.Argument(this.baseKey.IsValidInputSize(inputCount), nameof(inputCount), "Length is not a non-zero multiple of block size and no padding is selected."); if (inputCount == 0) { return(EmptyBuffer); } break; case SymmetricAlgorithmPadding.PKCS7: break; case SymmetricAlgorithmPadding.Zeros: // We have to implement this padding ourselves. if (inputCount == 0) { return(EmptyBuffer); } CryptoUtilities.ApplyZeroPadding( ref inputBuffer, this.baseKey.symmetricAlgorithmProvider.BlockLength, ref inputOffset, ref inputCount); break; default: throw new NotSupportedException(); } int cbResult; BCryptEncrypt( this.platformKey, new ArraySegment <byte>(inputBuffer, inputOffset, inputCount), null, this.iv.AsArraySegment(), default(ArraySegment <byte>), out cbResult, this.baseKey.flags).ThrowOnError(); byte[] output = new byte[cbResult]; BCryptEncrypt( this.platformKey, new ArraySegment <byte>(inputBuffer, inputOffset, inputCount), null, this.iv.AsArraySegment(), new ArraySegment <byte>(output), out cbResult, this.baseKey.flags).ThrowOnError(); Array.Resize(ref output, cbResult); return(output); }
/// <inheritdoc /> protected internal override byte[] Encrypt(byte[] plaintext, byte[] iv) { Verify.Operation(!this.Mode.IsAuthenticated(), "Cannot encrypt using this function when using an authenticated block chaining mode."); var key = this.GetInitializedKey(ref this.encryptorKey, iv); switch (this.Padding) { case SymmetricAlgorithmPadding.None: Requires.Argument(this.IsValidInputSize(plaintext.Length), nameof(plaintext), "Length is not a non-zero multiple of block size and no padding is selected."); break; case SymmetricAlgorithmPadding.PKCS7: break; case SymmetricAlgorithmPadding.Zeros: // We have to implement this padding ourselves. if (plaintext.Length == 0) { return(plaintext); } CryptoUtilities.ApplyZeroPadding(ref plaintext, this.symmetricAlgorithmProvider.BlockLength); break; default: throw new NotSupportedException(); } // We use the IV if the caller passes it in, or use // the resulting IV of the last cipher operation if the caller // did not specify an IV. // Copy the IV because the native code changes it, and // our contract with the caller is that we don't. this.encryptorIv = CopyBufferOrNull(iv) ?? this.encryptorIv; byte[] cipherText = BCryptEncrypt( key, plaintext, IntPtr.Zero, this.encryptorIv, this.flags).ToArray(); return(cipherText); }
/// <inheritdoc /> public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { if (this.mode.IsBlockCipher()) { if (this.padding == SymmetricAlgorithmPadding.Zeros) { // We apply Zeros padding ourselves because BouncyCastle for some reason // does it wrong. For example, if the input buffer is a block length already, // it will return an extra block of ciphertext (as if it added a block of // zeros, perhaps.) CryptoUtilities.ApplyZeroPadding(ref inputBuffer, this.transform.BlockSize, ref inputOffset, ref inputCount); } return(this.transform.DoFinal(inputBuffer, inputOffset, inputCount)); } else { return(this.transform.Update(inputBuffer, inputOffset, inputCount)); } }
/// <inheritdoc /> protected internal override byte[] Encrypt(byte[] data, byte[] iv) { bool paddingInUse = this.Padding != SymmetricAlgorithmPadding.None; Requires.Argument(iv == null || this.Mode.UsesIV(), nameof(iv), "IV supplied but does not apply to this cipher."); Verify.Operation(!this.Mode.IsAuthenticated(), "Cannot encrypt using this function when using an authenticated block chaining mode."); this.InitializeCipher(CipherMode.EncryptMode, iv, ref this.encryptingCipher); Requires.Argument(paddingInUse || this.IsValidInputSize(data.Length), nameof(data), "Length is not a multiple of block size and no padding is selected."); if (this.Padding == SymmetricAlgorithmPadding.Zeros) { // We apply Zeros padding ourselves because BouncyCastle for some reason // does it wrong. For example, if the input buffer is a block length already, // it will return an extra block of ciphertext (as if it added a block of // zeros, perhaps.) CryptoUtilities.ApplyZeroPadding(ref data, this.encryptingCipher.BlockSize); } return(this.DoCipherOperation(this.encryptingCipher, data)); }