< Summary

Class:Microsoft.Azure.KeyVault.SymmetricKey
Assembly:Microsoft.Azure.KeyVault.Cryptography
File(s):C:\Git\azure-sdk-for-net\sdk\keyvault\Microsoft.Azure.KeyVault.Cryptography\src\SymmetricKey.cs
Covered lines:34
Uncovered lines:81
Coverable lines:115
Total lines:325
Line coverage:29.5% (34 of 115)
Covered branches:24
Total branches:96
Branch coverage:25% (24 of 96)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.cctor()-0%100%
.ctor()-0%100%
.ctor(...)-0%100%
.ctor(...)-0%0%
.ctor(...)-70%71.43%
get_Kid()-100%100%
get_DefaultEncryptionAlgorithm()-0%0%
get_DefaultKeyWrapAlgorithm()-0%0%
get_DefaultSignatureAlgorithm()-0%100%
DecryptAsync(...)-0%0%
EncryptAsync(...)-0%0%
WrapKeyAsync(...)-64.29%50%
UnwrapKeyAsync(...)-64.29%50%
SignAsync(...)-0%100%
VerifyAsync(...)-0%100%
Dispose()-100%100%
Dispose(...)-100%100%

File(s)

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

#LineLine coverage
 1//
 2// Copyright (c) Microsoft Corporation. All rights reserved.
 3// Licensed under the MIT License. See License.txt in the project root for
 4// license information.
 5//
 6
 7using System;
 8using System.Security.Cryptography;
 9using System.Threading;
 10using System.Threading.Tasks;
 11using Microsoft.Azure.KeyVault.Core;
 12using Microsoft.Azure.KeyVault.Cryptography;
 13using Microsoft.Azure.KeyVault.Cryptography.Algorithms;
 14
 15#if NETSTANDARD
 16using TaskException = System.Threading.Tasks.Task;
 17#endif
 18
 19namespace Microsoft.Azure.KeyVault
 20{
 21    /// <summary>
 22    /// A simple Symmetric Key
 23    /// </summary>
 24    public class SymmetricKey : IKey
 25    {
 26        public const int KeySize128 = 128 >> 3;
 27        public const int KeySize192 = 192 >> 3;
 28        public const int KeySize256 = 256 >> 3;
 29        public const int KeySize384 = 384 >> 3;
 30        public const int KeySize512 = 512 >> 3;
 31
 032        private static readonly int                   DefaultKeySize = KeySize256;
 033        private static readonly RandomNumberGenerator Rng            = RandomNumberGenerator.Create();
 34
 35        private byte[] _key;
 36        private bool   _isDisposed;
 37
 38        /// <summary>
 39        /// Default constructor
 40        /// </summary>
 41        public SymmetricKey()
 042            : this( Guid.NewGuid().ToString( "N" ), DefaultKeySize )
 43        {
 044        }
 45
 46        /// <summary>
 47        /// Constructor.
 48        /// </summary>
 49        /// <param name="kid">The key identifier to use</param>
 50        public SymmetricKey( string kid )
 051            : this( kid, DefaultKeySize )
 52        {
 053        }
 54
 55        /// <summary>
 56        /// Constructor
 57        /// </summary>
 58        /// <param name="kid">The key identifier to use</param>
 59        /// <param name="keySize">The key size in bytes</param>
 060        public SymmetricKey( string kid, int keySize )
 61        {
 062            if ( string.IsNullOrWhiteSpace( kid ) )
 063                throw new ArgumentNullException( "kid" );
 64
 065            if ( keySize != KeySize128 && keySize != KeySize192 && keySize != KeySize256 && keySize != KeySize384 && key
 066                throw new ArgumentOutOfRangeException( "keySize", "The key size must be 128, 192, 256, 384 or 512 bits o
 67
 068            Kid = kid;
 069            _key = new byte[keySize];
 70
 071            Rng.GetBytes( _key );
 072        }
 73
 74        /// <summary>
 75        /// Constructor
 76        /// </summary>
 77        /// <param name="kid">The key identifier</param>
 78        /// <param name="keyBytes">The key material</param>
 3679        public SymmetricKey( string kid, byte[] keyBytes )
 80        {
 3681            if ( string.IsNullOrWhiteSpace( kid ) )
 082                throw new ArgumentNullException( "kid" );
 83
 3684            if ( keyBytes == null )
 085                throw new ArgumentNullException( "keyBytes" );
 86
 3687            if ( keyBytes.Length != KeySize128 && keyBytes.Length != KeySize192 && keyBytes.Length != KeySize256 && keyB
 088                throw new ArgumentOutOfRangeException( "keyBytes", "The key material must be 128, 192, 256, 384 or 512 b
 89
 3690            Kid = kid;
 3691            _key = keyBytes;
 3692        }
 93
 94        #region IKey Implementation
 95
 4896        public string Kid { get; protected set; }
 97
 98        public string DefaultEncryptionAlgorithm
 99        {
 100            get
 101            {
 0102                switch ( _key.Length )
 103                {
 104                    case KeySize128:
 0105                        return Aes128Cbc.AlgorithmName;
 106
 107                    case KeySize192:
 0108                        return Aes192Cbc.AlgorithmName;
 109
 110                    case KeySize256:
 0111                        return Aes128CbcHmacSha256.AlgorithmName;
 112
 113                    case KeySize384:
 0114                        return Aes192CbcHmacSha384.AlgorithmName;
 115
 116                    case KeySize512:
 0117                        return Aes256CbcHmacSha512.AlgorithmName;
 118                }
 119
 0120                return null;
 121            }
 122        }
 123
 124        public string DefaultKeyWrapAlgorithm
 125        {
 126            get
 127            {
 0128                switch ( _key.Length )
 129                {
 130                    case KeySize128:
 0131                        return AesKw128.AlgorithmName;
 132
 133                    case KeySize192:
 0134                        return AesKw192.AlgorithmName;
 135
 136                    case KeySize256:
 0137                        return AesKw256.AlgorithmName;
 138
 139                    case KeySize384:
 140                        // Default to longest allowed key length for wrap
 0141                        return AesKw256.AlgorithmName;
 142
 143                    case KeySize512:
 144                        // Default to longest allowed key length for wrap
 0145                        return AesKw256.AlgorithmName;
 146                }
 147
 0148                return null;
 149            }
 150        }
 151
 152        public string DefaultSignatureAlgorithm
 153        {
 0154            get { return null; }
 155        }
 156
 157
 158        public Task<byte[]> DecryptAsync( byte[] ciphertext, byte[] iv, byte[] authenticationData = null, byte[] authent
 159        {
 0160            if ( _isDisposed )
 0161                throw new ObjectDisposedException( string.Format( "SymmetricKey {0} is disposed", Kid ) );
 162
 0163            if ( string.IsNullOrWhiteSpace( algorithm ) )
 0164                algorithm = DefaultEncryptionAlgorithm;
 165
 0166            if ( ciphertext == null )
 0167                throw new ArgumentNullException( "ciphertext" );
 168
 0169            if ( iv == null )
 0170                throw new ArgumentNullException( "iv" );
 171
 0172            var algo = AlgorithmResolver.Default[algorithm] as SymmetricEncryptionAlgorithm;
 173
 0174            if ( algo == null )
 0175                throw new NotSupportedException( algorithm );
 176
 177            try
 178            {
 0179                using ( var encryptor = algo.CreateDecryptor( _key, iv, authenticationData, authenticationTag ) )
 180                {
 0181                    return Task.FromResult( encryptor.TransformFinalBlock( ciphertext, 0, ciphertext.Length ) );
 182                }
 183            }
 184            catch ( Exception ex )
 185            {
 0186                return TaskException.FromException<byte[]>( ex );
 187            }
 0188        }
 189
 190        public Task<Tuple<byte[], byte[], string>> EncryptAsync( byte[] plaintext, byte[] iv, byte[] authenticationData 
 191        {
 0192            if ( _isDisposed )
 0193                throw new ObjectDisposedException( string.Format( "SymmetricKey {0} is disposed", Kid ) );
 194
 0195            if ( string.IsNullOrWhiteSpace( algorithm ) )
 0196                algorithm = DefaultEncryptionAlgorithm;
 197
 0198            if ( plaintext == null )
 0199                throw new ArgumentNullException( "plaintext" );
 200
 0201            if ( iv == null )
 0202                throw new ArgumentNullException( "iv" );
 203
 0204            var algo = AlgorithmResolver.Default[algorithm] as SymmetricEncryptionAlgorithm;
 205
 0206            if ( algo == null )
 0207                throw new NotSupportedException( algorithm );
 208
 209            try
 210            {
 0211                using ( var encryptor = algo.CreateEncryptor( _key, iv, authenticationData ) )
 212                {
 0213                    var    cipherText        = encryptor.TransformFinalBlock( plaintext, 0, plaintext.Length );
 0214                    byte[] authenticationTag = null;
 0215                    var    transform         = encryptor as IAuthenticatedCryptoTransform;
 216
 0217                    if ( transform != null )
 218                    {
 0219                        authenticationTag = transform.Tag.Clone() as byte[];
 220                    }
 221
 0222                    var result = new Tuple<byte[], byte[], string>( cipherText, authenticationTag, algorithm );
 223
 0224                    return Task.FromResult( result );
 225                }
 226            }
 227            catch ( Exception ex )
 228            {
 0229                return TaskException.FromException<Tuple<byte[], byte[], string>>( ex );
 230            }
 0231        }
 232
 233        public Task<Tuple<byte[], string>> WrapKeyAsync( byte[] key, string algorithm = null, CancellationToken token = 
 234        {
 12235            if ( _isDisposed )
 0236                throw new ObjectDisposedException( string.Format( "SymmetricKey {0} is disposed", Kid ) );
 237
 12238            if ( string.IsNullOrWhiteSpace( algorithm ) )
 0239                algorithm = DefaultKeyWrapAlgorithm;
 240
 12241            if ( key == null || key.Length == 0 )
 0242                throw new ArgumentNullException( "key" );
 243
 12244            var algo = AlgorithmResolver.Default[algorithm] as KeyWrapAlgorithm;
 245
 12246            if ( algo == null )
 0247                throw new NotSupportedException( algorithm );
 248
 249            try
 250            {
 12251                using ( var encryptor = algo.CreateEncryptor( _key, null ) )
 252                {
 12253                        var result = new Tuple<byte[], string>( encryptor.TransformFinalBlock( key, 0, key.Length ), alg
 254
 12255                        return Task.FromResult( result );
 256                }
 257            }
 258            catch ( Exception ex )
 259            {
 0260                return TaskException.FromException<Tuple<byte[], string>>( ex );
 261            }
 12262        }
 263
 264        public Task<byte[]> UnwrapKeyAsync( byte[] encryptedKey, string algorithm = null, CancellationToken token = defa
 265        {
 12266            if ( _isDisposed )
 0267                throw new ObjectDisposedException( string.Format( "SymmetricKey {0} is disposed", Kid ) );
 268
 12269            if ( string.IsNullOrWhiteSpace( algorithm ) )
 0270                algorithm = DefaultKeyWrapAlgorithm;
 271
 12272            if ( encryptedKey == null || encryptedKey.Length == 0 )
 0273                throw new ArgumentNullException( "encryptedKey" );
 274
 12275            var algo = AlgorithmResolver.Default[algorithm] as KeyWrapAlgorithm;
 276
 12277            if ( algo == null )
 0278                throw new NotSupportedException( algorithm );
 279
 280            try
 281            {
 12282                using ( var encryptor = algo.CreateDecryptor( _key, null ) )
 283                {
 12284                    var result = encryptor.TransformFinalBlock( encryptedKey, 0, encryptedKey.Length );
 285
 12286                    return Task.FromResult( result );
 287                }
 288            }
 289            catch ( Exception ex )
 290            {
 0291                return TaskException.FromException<byte[]>( ex );
 292            }
 12293        }
 294
 295        public Task<Tuple<byte[], string>> SignAsync( byte[] digest, string algorithm = null, CancellationToken token = 
 296        {
 0297            return TaskException.FromException<Tuple<byte[], string>>( new NotImplementedException() );
 298        }
 299
 300        public Task<bool> VerifyAsync( byte[] digest, byte[] signature, string algorithm = null, CancellationToken token
 301        {
 0302            return TaskException.FromException<bool>( new NotImplementedException() );
 303        }
 304
 305        #endregion
 306
 307        public void Dispose()
 308        {
 12309            Dispose( true );
 12310            GC.SuppressFinalize( this );
 12311        }
 312
 313        protected virtual void Dispose( bool disposing )
 314        {
 12315            if ( disposing )
 316            {
 12317                if ( !_isDisposed )
 318                {
 12319                    _isDisposed = true;
 12320                    _key.Zero();
 321                }
 322            }
 12323        }
 324    }
 325}