private PinnedBuffer EncryptInCbcMode(PinnedBuffer plaintext, PinnedBuffer privateKey, PinnedBuffer initializationVector) { initializationVector.RejectIf().IsNull(nameof(initializationVector)).OrIf(argument => argument.Count() != BlockSizeInBytes, nameof(privateKey), "The length of the specified initialization vector is invalid for the algorithm."); using (var encryptionProvider = InitializeProvider()) { encryptionProvider.BlockSize = BlockSizeInBits; encryptionProvider.KeySize = KeySizeInBits; encryptionProvider.Mode = Mode; encryptionProvider.Padding = PaddingMode; encryptionProvider.Key = privateKey; encryptionProvider.IV = initializationVector; using (var encryptor = encryptionProvider.CreateEncryptor(privateKey, initializationVector)) { using (var memoryStream = new MemoryStream()) { using (var cryptographicStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)) { cryptographicStream.Write(plaintext, 0, plaintext.Length); cryptographicStream.FlushFinalBlock(); return(new PinnedBuffer(initializationVector.Concat(memoryStream.ToArray()).ToArray(), false)); } } } } }
internal PinnedBuffer Decrypt(PinnedBuffer ciphertext, PinnedBuffer privateKey) { ciphertext.RejectIf().IsNull(nameof(ciphertext)).OrIf(argument => argument.Count() < BlockSizeInBytes, nameof(ciphertext), "The length of the specified ciphertext is invalid for the algorithm."); privateKey.RejectIf().IsNull(nameof(privateKey)).OrIf(argument => argument.Count() != KeySizeInBytes, nameof(privateKey), "The length of the specified key is invalid for the algorithm."); switch (Mode) { case CipherMode.CBC: return(DecryptInCbcMode(ciphertext, privateKey)); case CipherMode.ECB: return(DecryptInEcbMode(ciphertext, privateKey)); default: throw new InvalidOperationException($"The specified cipher mode, {Mode}, is not supported."); } }
/// <summary> /// Generates a new <see cref="SecureSymmetricKey" />. /// </summary> /// <param name="algorithm"> /// The symmetric-key algorithm that the generated key is derived to interoperate with. The default value is /// <see cref="SymmetricAlgorithmSpecification.Aes256Cbc" />. /// </param> /// <param name="derivationMode"> /// The mode used to derive the generated key. The default value is /// <see cref="SecureSymmetricKeyDerivationMode.XorLayeringWithSubstitution" />. /// </param> /// <param name="keySource"> /// A buffer comprising 384 bytes (3,072 bits) from which the private key is derived. /// </param> /// <returns> /// A new <see cref="SecureSymmetricKey" />. /// </returns> /// <exception cref="ArgumentException"> /// <paramref name="keySource" /> is not 384 bytes in length. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="algorithm" /> is equal to <see cref="SymmetricAlgorithmSpecification.Unspecified" /> -or- /// <paramref name="derivationMode" /> is equal to <see cref="SecureSymmetricKeyDerivationMode.Unspecified" />. /// </exception> public static SecureSymmetricKey New(SymmetricAlgorithmSpecification algorithm, SecureSymmetricKeyDerivationMode derivationMode, PinnedBuffer keySource) { keySource.RejectIf(argument => argument.Length != KeySourceLengthInBytes, nameof(keySource), $"The key source is not {KeySourceLengthInBytes} bytes in length."); return(new SecureSymmetricKey(algorithm, derivationMode, keySource)); }