/// <summary> /// Trys to adds a <see cref="SignatureProvider"/> to this cache. /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to cache.</param> /// <exception cref="ArgumentNullException">if signatureProvider is null.</exception> /// <returns>true if the <see cref="SignatureProvider"/> was added, false if the cache already contained the <see cref="SignatureProvider"/></returns> /// <remarks>if the <see cref="SignatureProvider"/> is added <see cref="SignatureProvider.CryptoProviderCache"/> will be set to 'this'.</remarks> public override bool TryAdd(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } var cacheKey = GetCacheKey(signatureProvider); if (signatureProvider.WillCreateSignatures) { if (_signingSignatureProviders.TryAdd(cacheKey, signatureProvider)) { signatureProvider.CryptoProviderCache = this; return(true); } } else { if (_verifyingSignatureProviders.TryAdd(cacheKey, signatureProvider)) { signatureProvider.CryptoProviderCache = this; return(true); } } return(false); }
/// <summary> /// Trys to remove a <see cref="SignatureProvider"/> from this cache. /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to remove.</param> /// <exception cref="ArgumentNullException">if signatureProvider is null.</exception> /// <returns>true if the <see cref="SignatureProvider"/> was removed, false if the <see cref="SignatureProvider"/> was not found.</returns> /// <remarks>if the <see cref="SignatureProvider"/> is removed <see cref="SignatureProvider.CryptoProviderCache"/> will be set to null.</remarks> public override bool TryRemove(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } if (!ReferenceEquals(signatureProvider.CryptoProviderCache, this)) { return(false); } var cacheKey = GetCacheKey(signatureProvider); EventBasedLRUCache <string, SignatureProvider> signatureProviderCache; // Determine if we are caching a signing or a verifying SignatureProvider. if (signatureProvider.WillCreateSignatures) { signatureProviderCache = _signingSignatureProviders; } else { signatureProviderCache = _verifyingSignatureProviders; } try { return(signatureProviderCache.TryRemove(cacheKey, out SignatureProvider provider)); } catch (Exception ex) { LogHelper.LogWarning(LogHelper.FormatInvariant(LogMessages.IDX10699, cacheKey, ex)); return(false); } }
/// <summary> /// Trys to adds a <see cref="SignatureProvider"/> to this cache. /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to cache.</param> /// <exception cref="ArgumentNullException">if signatureProvider is null.</exception> /// <returns> /// <c>true</c> if the <see cref="SignatureProvider"/> was added, <c>false</c> if the cache already contained the <see cref="SignatureProvider"/> or if <see cref="SignatureProvider"/> should not be cached. /// </returns> /// <remarks>if the <see cref="SignatureProvider"/> is added <see cref="SignatureProvider.CryptoProviderCache"/> will be set to 'this'.</remarks> public override bool TryAdd(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } var cacheKey = GetCacheKey(signatureProvider); EventBasedLRUCache <string, SignatureProvider> signatureProviderCache; // Determine if we are caching a signing or a verifying SignatureProvider. if (signatureProvider.WillCreateSignatures) { signatureProviderCache = _signingSignatureProviders; } else { signatureProviderCache = _verifyingSignatureProviders; } // The cache does NOT already have a crypto provider associated with this key. if (!signatureProviderCache.Contains(cacheKey)) { signatureProviderCache.SetValue(cacheKey, signatureProvider); signatureProvider.CryptoProviderCache = this; return(true); } return(false); }
/// <summary> /// Trys to remove a <see cref="SignatureProvider"/> from this cache. /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to remove.</param> /// <exception cref="ArgumentNullException">if signatureProvider is null.</exception> /// <returns>true if the <see cref="SignatureProvider"/> was removed, false if the <see cref="SignatureProvider"/> was not found.</returns> /// <remarks>if the <see cref="SignatureProvider"/> is removed <see cref="SignatureProvider.CryptoProviderCache"/> will be set to null.</remarks> public override bool TryRemove(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } if (!ReferenceEquals(signatureProvider.CryptoProviderCache, this)) { return(false); } var cacheKey = GetCacheKey(signatureProvider); if (signatureProvider.WillCreateSignatures) { if (_signingSignatureProviders.TryRemove(cacheKey, out SignatureProvider provider)) { provider.CryptoProviderCache = null; return(true); } } else { if (_verifyingSignatureProviders.TryRemove(cacheKey, out SignatureProvider provider)) { provider.CryptoProviderCache = null; return(true); } } return(false); }
/// <summary> /// When finished with a <see cref="SignatureProvider"/> call this method for cleanup. The default behavior is to call <see cref="SignatureProvider.Dispose()"/> /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to be released.</param> public virtual void ReleaseSignatureProvider(SignatureProvider signatureProvider) { if (signatureProvider != null) { signatureProvider.Dispose(); } }
private void OnSignatureProviderRemovedFromCache(SignatureProvider signatureProvider) { signatureProvider.CryptoProviderCache = null; if (signatureProvider.RefCount == 0) { signatureProvider.Dispose(); } }
/// <summary> /// Returns the cache key to use when looking up an entry into the cache for a <see cref="SignatureProvider" /> /// </summary> /// <param name="signatureProvider">the <see cref="SignatureProvider"/> to create the key for.</param> /// <exception cref="ArgumentNullException">if signatureProvider is null.</exception> /// <returns>the cache key to use for finding a <see cref="SignatureProvider"/>.</returns> protected override string GetCacheKey(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } return(GetCacheKeyPrivate(signatureProvider.Key, signatureProvider.Algorithm, signatureProvider.GetType().ToString())); }
/// <summary> /// When finished with a <see cref="SignatureProvider"/> call this method for cleanup. The default behavior is to call <see cref="SignatureProvider.Dispose()"/> /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to be released.</param> public virtual void ReleaseSignatureProvider(SignatureProvider signatureProvider) { if (signatureProvider == null) { throw LogHelper.LogArgumentNullException(nameof(signatureProvider)); } else if (CustomCryptoProvider != null && CustomCryptoProvider.IsSupportedAlgorithm(signatureProvider.Algorithm)) { CustomCryptoProvider.Release(signatureProvider); } else if (signatureProvider.CryptoProviderCache == null) { signatureProvider.Dispose(); } }
/// <summary> /// Trys to find a <see cref="SignatureProvider"/> to this cache. /// </summary> /// <param name="securityKey">the key that is used to by the crypto provider.</param> /// <param name="algorithm">the algorithm that is used by the crypto provider.</param> /// <param name="typeofProvider">the typeof the crypto provider obtained by calling object.GetType().</param> /// <param name="willCreateSignatures">a bool to indicate if the <see cref="SignatureProvider"/> will be used to sign.</param> /// <param name="signatureProvider">the <see cref="SignatureProvider"/> if found.</param> /// <exception cref="ArgumentNullException">if securityKey is null.</exception> /// <exception cref="ArgumentNullException">if algorithm is null or empty string.</exception> /// <exception cref="ArgumentNullException">if typeofProvider is null or empty string.</exception> /// <returns>true if a <see cref="SignatureProvider"/> was found, false otherwise.</returns> public override bool TryGetSignatureProvider(SecurityKey securityKey, string algorithm, string typeofProvider, bool willCreateSignatures, out SignatureProvider signatureProvider) { if (securityKey == null) { throw LogHelper.LogArgumentNullException(nameof(securityKey)); } if (string.IsNullOrEmpty(algorithm)) { throw LogHelper.LogArgumentNullException(nameof(algorithm)); } if (string.IsNullOrEmpty(typeofProvider)) { throw LogHelper.LogArgumentNullException(nameof(typeofProvider)); } var cacheKey = GetCacheKeyPrivate(securityKey, algorithm, typeofProvider); if (willCreateSignatures) { return(_signingSignatureProviders.TryGetValue(cacheKey, out signatureProvider)); } else { return(_verifyingSignatureProviders.TryGetValue(cacheKey, out signatureProvider)); } }
private SignatureProvider CreateSignatureProvider(SecurityKey key, string algorithm, bool willCreateSignatures) { if (key == null) { throw LogHelper.LogArgumentNullException(nameof(key)); } if (string.IsNullOrEmpty(algorithm)) { throw LogHelper.LogArgumentNullException(nameof(algorithm)); } if (CustomCryptoProvider != null && CustomCryptoProvider.IsSupportedAlgorithm(algorithm, key, willCreateSignatures)) { SignatureProvider signatureProvider = CustomCryptoProvider.Create(algorithm, key, willCreateSignatures) as SignatureProvider; if (signatureProvider == null) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10646, algorithm, key, typeof(SignatureProvider)))); } return(signatureProvider); } if (!IsSupportedAlgorithm(algorithm, key)) { throw LogHelper.LogExceptionMessage(new ArgumentException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10634, algorithm, key))); } AsymmetricSecurityKey asymmetricKey = key as AsymmetricSecurityKey; if (asymmetricKey != null) { return(new AsymmetricSignatureProvider(asymmetricKey, algorithm, willCreateSignatures)); } SymmetricSecurityKey symmetricKey = key as SymmetricSecurityKey; if (symmetricKey != null) { return(new SymmetricSignatureProvider(symmetricKey, algorithm)); } JsonWebKey jsonWebKey = key as JsonWebKey; if (jsonWebKey != null) { if (jsonWebKey.Kty != null) { if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.RSA || jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.EllipticCurve) { return(new AsymmetricSignatureProvider(key, algorithm, willCreateSignatures)); } if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.Octet) { return(new SymmetricSignatureProvider(key, algorithm)); } } } // TODO improve this message. Nothing about JsonWebKey is mentioned. throw LogHelper.LogExceptionMessage(new ArgumentException(String.Format(CultureInfo.InvariantCulture, LogMessages.IDX10600, typeof(SignatureProvider), typeof(SecurityKey), typeof(AsymmetricSecurityKey), typeof(SymmetricSecurityKey), key.GetType()))); }
private SignatureProvider CreateProvider(SecurityKey key, string algorithm, bool willCreateSignatures) { if (key == null) { throw LogHelper.LogArgumentNullException(nameof(key)); } if (string.IsNullOrWhiteSpace(algorithm)) { throw LogHelper.LogArgumentNullException(nameof(algorithm)); } if (CustomCryptoProvider != null && CustomCryptoProvider.IsSupportedAlgorithm(algorithm, key, willCreateSignatures)) { SignatureProvider signatureProvider = CustomCryptoProvider.Create(algorithm, key, willCreateSignatures) as SignatureProvider; if (signatureProvider == null) { throw LogHelper.LogException <InvalidOperationException>(LogMessages.IDX10646, key, algorithm, typeof(SignatureProvider)); } return(signatureProvider); } if (!IsSupportedAlgorithm(algorithm, key)) { throw LogHelper.LogException <ArgumentException>(LogMessages.IDX10634, algorithm, key); } AsymmetricSecurityKey asymmetricKey = key as AsymmetricSecurityKey; if (asymmetricKey != null) { return(new AsymmetricSignatureProvider(asymmetricKey, algorithm, willCreateSignatures)); } SymmetricSecurityKey symmetricKey = key as SymmetricSecurityKey; if (symmetricKey != null) { return(new SymmetricSignatureProvider(symmetricKey, algorithm)); } JsonWebKey jsonWebKey = key as JsonWebKey; if (jsonWebKey != null) { if (jsonWebKey.Kty != null) { if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.RSA || jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.EllipticCurve) { return(new AsymmetricSignatureProvider(key, algorithm, willCreateSignatures)); } if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.Octet) { return(new SymmetricSignatureProvider(key, algorithm)); } } } throw LogHelper.LogException <ArgumentException>(LogMessages.IDX10600, typeof(SignatureProvider), typeof(SecurityKey), typeof(AsymmetricSecurityKey), typeof(SymmetricSecurityKey), key.GetType()); }
/// <summary> /// For some security key types, in some runtimes, it's not possible to extract public key material and create an <see cref="SecurityKey.InternalId"/>. /// In these cases, <see cref="SecurityKey.InternalId"/> will be an empty string, and these keys should not be cached. /// </summary> /// <param name="signatureProvider"><see cref="SignatureProvider"/> to be examined.</param> /// <returns><c>True</c> if <paramref name="signatureProvider"/> should be cached, <c>false</c> otherwise.</returns> private static bool ShouldCacheSignatureProvider(SignatureProvider signatureProvider) { return(signatureProvider.Key.InternalId.Length != 0); }
private SignatureProvider CreateSignatureProvider(SecurityKey key, string algorithm, bool willCreateSignatures) { if (key == null) { throw LogHelper.LogArgumentNullException(nameof(key)); } if (string.IsNullOrEmpty(algorithm)) { throw LogHelper.LogArgumentNullException(nameof(algorithm)); } SignatureProvider signatureProvider = null; if (CustomCryptoProvider != null && CustomCryptoProvider.IsSupportedAlgorithm(algorithm, key, willCreateSignatures)) { signatureProvider = CustomCryptoProvider.Create(algorithm, key, willCreateSignatures) as SignatureProvider; if (signatureProvider == null) { throw LogHelper.LogExceptionMessage(new InvalidOperationException(LogHelper.FormatInvariant(LogMessages.IDX10646, algorithm, key, typeof(SignatureProvider)))); } return(signatureProvider); } // types are checked in order of expected occurrence string typeofSignatureProvider = null; bool createAsymmetric = true; if (key is AsymmetricSecurityKey asymmetricSecurityKey) { typeofSignatureProvider = typeof(AsymmetricSignatureProvider).ToString(); } else if (key is JsonWebKey jsonWebKey) { if (jsonWebKey.Kty != null) { if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.RSA || jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.EllipticCurve) { typeofSignatureProvider = typeof(AsymmetricSignatureProvider).ToString(); } if (jsonWebKey.Kty == JsonWebAlgorithmsKeyTypes.Octet) { typeofSignatureProvider = typeof(SymmetricSignatureProvider).ToString(); createAsymmetric = false; } } } else if (key is SymmetricSecurityKey symmetricSecurityKey) { typeofSignatureProvider = typeof(SymmetricSignatureProvider).ToString(); createAsymmetric = false; } if (typeofSignatureProvider == null) { throw LogHelper.LogExceptionMessage(new NotSupportedException(LogHelper.FormatInvariant(LogMessages.IDX10621, typeof(SymmetricSignatureProvider), typeof(SecurityKey), typeof(AsymmetricSecurityKey), typeof(SymmetricSecurityKey), key.GetType()))); } if (!IsSupportedAlgorithm(algorithm, key)) { throw LogHelper.LogExceptionMessage(new NotSupportedException(LogHelper.FormatInvariant(LogMessages.IDX10634, algorithm, key))); } if (CacheSignatureProviders) { if (CryptoProviderCache.TryGetSignatureProvider(key, algorithm, typeofSignatureProvider, willCreateSignatures, out signatureProvider)) { return(signatureProvider); } lock (_cacheLock) { if (CryptoProviderCache.TryGetSignatureProvider(key, algorithm, typeofSignatureProvider, willCreateSignatures, out signatureProvider)) { return(signatureProvider); } if (createAsymmetric) { signatureProvider = new AsymmetricSignatureProvider(key, algorithm, willCreateSignatures, this); } else { signatureProvider = new SymmetricSignatureProvider(key, algorithm, willCreateSignatures); } CryptoProviderCache.TryAdd(signatureProvider); } } else if (createAsymmetric) { signatureProvider = new AsymmetricSignatureProvider(key, algorithm, willCreateSignatures); } else { signatureProvider = new SymmetricSignatureProvider(key, algorithm, willCreateSignatures); } return(signatureProvider); }