Пример #1
0
        /// <summary>
        /// Decodes source stream into destionation stream as an asynchronous operation.
        /// </summary>
        /// <param name="source">The source stream.</param>
        /// <param name="destination">The destionation stream.</param>
        /// <param name="keyLocator">The function which is able to locate the keying material based on the keying material identificator.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public static async Task DecodeAsync(Stream source, Stream destination, Func <string, byte[]> keyLocator)
        {
            ValidateDecodeParameters(source, destination, keyLocator);

            CodingHeader codingHeader = await ReadCodingHeaderAsync(source).ConfigureAwait(false);

            byte[] pseudorandomKey      = HmacSha256(codingHeader.Salt, keyLocator(codingHeader.KeyId));
            byte[] contentEncryptionKey = GetContentEncryptionKey(pseudorandomKey);

            await DecryptContentAsync(source, destination, codingHeader.RecordSize, pseudorandomKey, contentEncryptionKey).ConfigureAwait(false);
        }
Пример #2
0
        private static async Task WriteCodingHeaderAsync(Stream destination, CodingHeader codingHeader)
        {
            //+----------+---------------+-------------+-----------------+
            //| SALT(16) | RECORDSIZE(4) | KEYIDLEN(1) | KEYID(KEYIDLEN) |
            //+----------+---------------+-------------+-----------------+

            await destination.WriteAsync(codingHeader.Salt, 0, codingHeader.Salt.Length).ConfigureAwait(false);

            WriteRecordSize(destination, codingHeader.RecordSize);
            destination.WriteByte((byte)codingHeader.KeyId.Length);
            await destination.WriteAsync(codingHeader.KeyId, 0, codingHeader.KeyId.Length).ConfigureAwait(false);
        }
Пример #3
0
        private static async Task WriteCodingHeaderAsync(Stream destination, CodingHeader codingHeader)
        {
            //+----------+---------------+-------------+-----------------+
            //| SALT(16) | RECORDSIZE(4) | KEYIDLEN(1) | KEYID(KEYIDLEN) |
            //+----------+---------------+-------------+-----------------+

            byte[] keyIdBytes      = GetKeyIdBytes(codingHeader.KeyId);
            byte[] recordSizeBytes = GetRecordSizeBytes(codingHeader.RecordSize);

            byte[] codingHeaderBytes = new byte[SALT_LENGTH + RECORD_SIZE_LENGTH + KEY_ID_LEN_LENGTH + keyIdBytes.Length];

            codingHeader.Salt.CopyTo(codingHeaderBytes, SALT_INDEX);
            recordSizeBytes.CopyTo(codingHeaderBytes, RECORD_SIZE_INDEX);
            codingHeaderBytes[KEY_ID_LEN_INDEX] = (byte)keyIdBytes.Length;
            keyIdBytes.CopyTo(codingHeaderBytes, KEY_ID_INDEX);

            await destination.WriteAsync(codingHeaderBytes, 0, codingHeaderBytes.Length).ConfigureAwait(false);
        }
Пример #4
0
        /// <summary>
        /// Encodes source stream into destionation stream as an asynchronous operation.
        /// </summary>
        /// <param name="source">The source stream.</param>
        /// <param name="destination">The destionation stream.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="key">The keying material.</param>
        /// <param name="keyId">The keying material identificator.</param>
        /// <param name="recordSize">The record size in octets.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public static async Task EncodeAsync(Stream source, Stream destination, byte[] salt, byte[] key, string keyId, int recordSize)
        {
            ValidateEncodeParameters(source, destination, key, recordSize);

            CodingHeader codingHeader = new CodingHeader
            {
                Salt       = CoalesceSalt(salt),
                RecordSize = recordSize,
                KeyId      = keyId
            };

            // PRK = HMAC-SHA-256(salt, IKM)
            byte[] pseudorandomKey      = HmacSha256(codingHeader.Salt, key);
            byte[] contentEncryptionKey = GetContentEncryptionKey(pseudorandomKey);

            await WriteCodingHeaderAsync(destination, codingHeader).ConfigureAwait(false);

            await EncryptContentAsync(source, destination, codingHeader.RecordSize, pseudorandomKey, contentEncryptionKey).ConfigureAwait(false);
        }
Пример #5
0
        /// <summary>
        /// Decodes source stream into destionation stream as an asynchronous operation.
        /// </summary>
        /// <param name="source">The source stream.</param>
        /// <param name="destination">The destionation stream.</param>
        /// <param name="keyProvider">The function which is able to provide the keying material based on the keying material identificator.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public static async Task DecodeAsync(Stream source, Stream destination, Func <byte[], byte[]> keyProvider)
        {
            ValidateDecodeParameters(source, destination, keyProvider);

            CodingHeader codingHeader = await ReadCodingHeaderAsync(source).ConfigureAwait(false);

            // PRK = HMAC-SHA-256(salt, IKM)
            byte[] pseudorandomKey = HmacSha256(codingHeader.Salt, keyProvider(codingHeader.KeyId));

            byte[] contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash;
            using (HMACSHA256 pseudorandomKeyHasher = new HMACSHA256(pseudorandomKey))
            {
                // HMAC-SHA-256(PRK, CEK_INFO)
                contentEncryptionKeyInfoParameterHash = HmacSha256(pseudorandomKeyHasher, _contentEncryptionKeyInfoParameter);

                // HMAC-SHA-256(PRK, NONCE_INFO)
                nonceInfoParameterHash = HmacSha256(pseudorandomKeyHasher, _nonceInfoParameter);
            }

            await DecryptContentAsync(source, destination, codingHeader.RecordSize, contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash).ConfigureAwait(false);
        }
Пример #6
0
        /// <summary>
        /// Encodes source stream into destionation stream as an asynchronous operation.
        /// </summary>
        /// <param name="source">The source stream.</param>
        /// <param name="destination">The destionation stream.</param>
        /// <param name="salt">The salt.</param>
        /// <param name="key">The keying material.</param>
        /// <param name="keyId">The keying material identificator.</param>
        /// <param name="recordSize">The record size in octets.</param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public static async Task EncodeAsync(Stream source, Stream destination, byte[] salt, byte[] key, byte[] keyId, int recordSize)
        {
            ValidateEncodeParameters(source, destination, key, keyId, recordSize);

            CodingHeader codingHeader = new CodingHeader(CoalesceSalt(salt), recordSize, keyId ?? _arrayPool.Rent(0));

            // PRK = HMAC-SHA-256(salt, IKM)
            byte[] pseudorandomKey = HmacSha256(codingHeader.Salt, key);

            byte[] contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash;
            using (HMACSHA256 pseudorandomKeyHasher = new HMACSHA256(pseudorandomKey))
            {
                // HMAC-SHA-256(PRK, CEK_INFO)
                contentEncryptionKeyInfoParameterHash = HmacSha256(pseudorandomKeyHasher, _contentEncryptionKeyInfoParameter);

                // HMAC-SHA-256(PRK, NONCE_INFO)
                nonceInfoParameterHash = HmacSha256(pseudorandomKeyHasher, _nonceInfoParameter);
            }

            await WriteCodingHeaderAsync(destination, codingHeader).ConfigureAwait(false);

            await EncryptContentAsync(source, destination, codingHeader.RecordSize, contentEncryptionKeyInfoParameterHash, nonceInfoParameterHash).ConfigureAwait(false);
        }