< Summary

Class:Microsoft.Azure.KeyVault.CachingKeyResolver
Assembly:Microsoft.Azure.KeyVault.Extensions
File(s):C:\Git\azure-sdk-for-net\sdk\keyvault\Microsoft.Azure.KeyVault.Extensions\src\CachingKeyResolver.cs
Covered lines:38
Uncovered lines:13
Coverable lines:51
Total lines:193
Line coverage:74.5% (38 of 51)
Covered branches:17
Total branches:20
Branch coverage:85% (17 of 20)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-83.33%50%
ResolveKeyAsync()-85.71%80%
Dispose()-100%100%
Dispose(...)-100%100%
.ctor(...)-100%100%
get_Kid()-0%100%
get_DefaultEncryptionAlgorithm()-0%100%
get_DefaultKeyWrapAlgorithm()-0%100%
get_DefaultSignatureAlgorithm()-0%100%
DecryptAsync(...)-0%100%
EncryptAsync(...)-0%100%
WrapKeyAsync(...)-0%100%
UnwrapKeyAsync(...)-0%100%
SignAsync(...)-0%100%
VerifyAsync(...)-0%100%
Dispose()-100%100%
Dispose(...)-100%100%
Dispose(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\keyvault\Microsoft.Azure.KeyVault.Extensions\src\CachingKeyResolver.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License. See License.txt in the project root for
 3// license information.
 4
 5using System;
 6using System.Linq;
 7using System.Threading;
 8using System.Threading.Tasks;
 9using Microsoft.Azure.KeyVault.Core;
 10
 11namespace Microsoft.Azure.KeyVault
 12{
 13    /// <summary>
 14    /// A simple caching Key Resolver using a LRU cache
 15    /// </summary>
 16    public class CachingKeyResolver : IKeyResolver, IDisposable
 17    {
 18        private LRUCache<string, IKey> _cache;
 19        private IKeyResolver           _inner;
 20        private bool                   _isDisposed;
 21
 22        /// <summary>
 23        /// Constructor.
 24        /// </summary>
 25        /// <param name="capacity">The maximim capacity for the cache</param>
 26        /// <param name="inner">The IKeyResolver to wrap</param>
 1227        public CachingKeyResolver( int capacity, IKeyResolver inner )
 28        {
 1229            if ( inner == null )
 030                throw new ArgumentNullException( "inner" );
 31
 1232            _cache = new LRUCache<string, IKey>( capacity );
 1233            _inner = inner;
 1234        }
 35
 36        #region IKeyResolver
 37
 38        /// <summary>
 39        /// Resolve a key indicated by its ID to the corresponding <see cref="IKey"/>
 40        /// </summary>
 41        /// <param name="kid"> the key identifier </param>
 42        /// <param name="token"> the cancellation token </param>
 43        /// <returns> task result of the <see cref="IKey"/></returns>
 44        public async Task<IKey> ResolveKeyAsync( string kid, CancellationToken token )
 45        {
 10846            if ( _isDisposed )
 047                throw new ObjectDisposedException( "CachingKeyResolver" );
 48
 10849            if ( string.IsNullOrWhiteSpace( kid ) )
 050                throw new ArgumentNullException( "kid" );
 51
 10852            IKey result = _cache.Get( kid );
 53
 10854            if ( result == null )
 55            {
 3656                result = await _inner.ResolveKeyAsync( kid, token ).ConfigureAwait( false );
 3257                if ( result != null )
 58                {
 59                    // Cache the resolved key using the result's Kid.
 60                    // This is especially for the case when the resolved key contains information about the key version
 3261                    var cacheKid = string.IsNullOrWhiteSpace( result.Kid ) ? kid : result.Kid;
 62
 3263                    var cachedKey = new CacheKey(result);
 3264                    _cache.Add( cacheKid, cachedKey );
 3265                    return cachedKey;
 66                }
 67            }
 68
 7269            return result;
 10470        }
 71
 72        #endregion
 73
 74        /// <summary>
 75        /// Disposes the object
 76        /// </summary>
 77        public void Dispose()
 78        {
 1479            Dispose( true );
 1480            GC.SuppressFinalize( this );
 1481        }
 82
 83        protected virtual void Dispose( bool disposing )
 84        {
 1485            if ( disposing )
 86            {
 1487                if ( !_isDisposed )
 88                {
 1289                   _isDisposed = true;
 90
 5291                    foreach (var cacheKey in _cache.OfType<CacheKey>())
 92                    {
 1493                        cacheKey.Dispose(true);
 94                    }
 95
 1296                    _cache.Dispose();
 1297                    _cache = null;
 98                }
 99            }
 14100        }
 101
 102        # region CacheKey class
 103
 104        /// <summary>
 105        /// This class wraps the key that is cached using <see cref="CachingKeyResolver"/>
 106        /// The main purpose of <see cref="CacheKey"/> is to evict disposing cached key from the cache.
 107        /// </summary>
 108        class CacheKey : IKey
 109        {
 110            private readonly IKey _key;
 111
 32112            public CacheKey(IKey key)
 113            {
 32114                _key = key;
 32115            }
 116
 117            public string Kid
 118            {
 0119                get { return _key.Kid; }
 120            }
 121
 122            public string DefaultEncryptionAlgorithm
 123            {
 0124                get { return _key.DefaultEncryptionAlgorithm; }
 125            }
 126
 127            public string DefaultKeyWrapAlgorithm
 128            {
 0129                get { return _key.DefaultKeyWrapAlgorithm; }
 130            }
 131
 132            public string DefaultSignatureAlgorithm
 133            {
 0134                get { return _key.DefaultSignatureAlgorithm; }
 135            }
 136
 137            public Task<byte[]> DecryptAsync(byte[] ciphertext, byte[] iv, byte[] authenticationData = null, byte[] auth
 138            {
 0139                return _key.DecryptAsync(ciphertext, iv, authenticationData, authenticationTag, algorithm, token);
 140            }
 141
 142            public Task<Tuple<byte[], byte[], string>> EncryptAsync(byte[] plaintext, byte[] iv, byte[] authenticationDa
 143            {
 0144                return _key.EncryptAsync(plaintext, iv, authenticationData, algorithm, token);
 145            }
 146
 147            public Task<Tuple<byte[], string>> WrapKeyAsync(byte[] key, string algorithm = null, CancellationToken token
 148            {
 0149                return _key.WrapKeyAsync(key, algorithm, token);
 150            }
 151
 152            public Task<byte[]> UnwrapKeyAsync(byte[] encryptedKey, string algorithm = null, CancellationToken token = d
 153            {
 0154                return _key.UnwrapKeyAsync(encryptedKey, algorithm, token);
 155            }
 156
 157            public Task<Tuple<byte[], string>> SignAsync(byte[] digest, string algorithm = null, CancellationToken token
 158            {
 0159                return _key.SignAsync(digest, algorithm, token);
 160            }
 161
 162            public Task<bool> VerifyAsync(byte[] digest, byte[] signature, string algorithm = null, CancellationToken to
 163            {
 0164                return _key.VerifyAsync(digest, signature, algorithm, token);
 165            }
 166
 167            public void Dispose()
 168            {
 169                // do not dispose because there may be multiple references to the cached object
 2170            }
 171
 172            /// <summary>
 173            /// Disposes the cached key only when cache is disposing
 174            /// </summary>
 175            /// <param name="force"> whether to force dispose </param>
 176            internal void Dispose(bool force)
 177            {
 14178                Dispose(true, force);
 14179                GC.SuppressFinalize(this);
 14180            }
 181
 182            private void Dispose(bool disposing, bool force)
 183            {
 14184                if (disposing & force)
 185                {
 14186                    _key.Dispose();
 187                }
 14188            }
 189        }
 190
 191        # endregion CacheKey class
 192    }
 193}