private CascadingSymmetricKey(SecureSymmetricKeyDerivationMode derivationMode, params SymmetricAlgorithmSpecification[] algorithms) : base(ConcurrencyControlMode.SingleThreadLock) { Depth = algorithms.Length; Keys = new SecureSymmetricKey[Depth]; for (var i = 0; i < Depth; i++) { Keys[i] = SecureSymmetricKey.New(algorithms[i], derivationMode); } }
/// <summary> /// Decrypts the specified ciphertext. /// </summary> /// <param name="ciphertext"> /// The ciphertext to decrypt. /// </param> /// <param name="key"> /// The key derivation bits and algorithm specification used to transform the ciphertext. /// </param> /// <returns> /// The resulting plaintext object. /// </returns> /// <exception cref="SecurityException"> /// An exception was raised during decryption or deserialization. /// </exception> public T Decrypt(Byte[] ciphertext, SecureSymmetricKey key) { try { using (var keyBuffer = key.DeriveKey()) { return(Decrypt(ciphertext, keyBuffer, key.Algorithm)); } } catch { throw new SecurityException("The decryption operation failed."); } }
/// <summary> /// Encrypts the specified plaintext object. /// </summary> /// <param name="plaintextObject"> /// The plaintext object to encrypt. /// </param> /// <param name="key"> /// The key derivation bits and algorithm specification used to transform the object. /// </param> /// <param name="initializationVector"> /// An initialization vector with length greater than or equal to the block size for the specified cipher (extra bytes are /// ignored), or <see langword="null" /> to generate a random initialization vector. /// </param> /// <returns> /// The resulting ciphertext. /// </returns> /// <exception cref="SecurityException"> /// An exception was raised during encryption or serialization. /// </exception> public Byte[] Encrypt(T plaintextObject, SecureSymmetricKey key, Byte[] initializationVector) { try { using (var keyBuffer = key.DeriveKey()) { return(Encrypt(plaintextObject, keyBuffer, key.Algorithm, initializationVector)); } } catch { throw new SecurityException("The encryption operation failed."); } }
/// <summary> /// Creates a new instance of a <see cref="CascadingSymmetricKey" /> using the specified buffer. /// </summary> /// <param name="buffer"> /// A binary representation of a <see cref="CascadingSymmetricKey" />. /// </param> /// <returns> /// A new instance of a <see cref="CascadingSymmetricKey" />. /// </returns> /// <exception cref="ArgumentException"> /// <paramref name="buffer" /> is invalid. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="buffer" /> is <see langword="null" />. /// </exception> public static CascadingSymmetricKey FromBuffer(SecureBuffer buffer) { buffer.RejectIf().IsNull(nameof(buffer)).OrIf(argument => argument.Length != SerializedLength, nameof(buffer), "The specified buffer is invalid."); try { var keys = (SecureSymmetricKey[])null; buffer.Access(pinnedBuffer => { // Interrogate the final 16 bits to determine the depth. var keyLength = SecureSymmetricKey.SerializedLength; var depth = BitConverter.ToUInt16(pinnedBuffer, (SerializedLength - sizeof(UInt16))); keys = new SecureSymmetricKey[depth]; for (var i = 0; i < depth; i++) { using (var secureBuffer = new SecureBuffer(keyLength)) { secureBuffer.Access(keyBuffer => { // Copy out the key buffers. Array.Copy(pinnedBuffer, (keyLength * i), keyBuffer, 0, keyLength); }); keys[i] = SecureSymmetricKey.FromBuffer(secureBuffer); } } }); return(new CascadingSymmetricKey(keys)); } catch { throw new ArgumentException("The specified buffer is invalid.", nameof(buffer)); } }
/// <summary> /// Creates a new instance of a <see cref="SecureSymmetricKey" /> using the specified buffer. /// </summary> /// <param name="buffer"> /// A binary representation of a <see cref="SecureSymmetricKey" />. /// </param> /// <returns> /// A new instance of a <see cref="SecureSymmetricKey" />. /// </returns> /// <exception cref="ArgumentException"> /// <paramref name="buffer" /> is invalid. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="buffer" /> is <see langword="null" />. /// </exception> public static SecureSymmetricKey FromBuffer(SecureBuffer buffer) { buffer.RejectIf().IsNull(nameof(buffer)).OrIf(argument => argument.Length != SerializedLength, nameof(buffer), "The specified buffer is invalid."); try { var result = (SecureSymmetricKey)null; buffer.Access(pinnedCiphertext => { using (var plaintextBuffer = new PinnedBuffer(SerializedPlaintextLength, true)) { using (var cipher = BufferEncryptionAlgorithm.ToCipher(RandomnessProvider)) { using (var plaintext = cipher.Decrypt(pinnedCiphertext, BufferEncryptionKey)) { Array.Copy(plaintext, 0, plaintextBuffer, 0, SerializedPlaintextLength); } } using (var keySource = new PinnedBuffer(KeySourceLengthInBytes, true)) { Array.Copy(plaintextBuffer, KeySourceBufferIndex, keySource, 0, KeySourceLengthInBytes); var algorithm = (SymmetricAlgorithmSpecification)plaintextBuffer[AlgorithmBufferIndex]; var derivationMode = (SecureSymmetricKeyDerivationMode)plaintextBuffer[DerivationModeBufferIndex]; result = new SecureSymmetricKey(algorithm, derivationMode, keySource); } } }); return(result); } catch { throw new ArgumentException("The specified buffer is invalid.", nameof(buffer)); } }
/// <summary> /// Encrypts the specified plaintext object. /// </summary> /// <param name="plaintextObject"> /// The plaintext object to encrypt. /// </param> /// <param name="key"> /// The key derivation bits and algorithm specification used to transform the object. /// </param> /// <returns> /// The resulting ciphertext. /// </returns> /// <exception cref="SecurityException"> /// An exception was raised during encryption or serialization. /// </exception> public Byte[] Encrypt(T plaintextObject, SecureSymmetricKey key) => Encrypt(plaintextObject, key, null);