public bool TryGetKey( Guid keyId, out JsonWebKey key ) {
			foreach( JsonWebKey currentKey in m_keys ) {
				if( currentKey.Id == keyId ) {
					key = currentKey;
					return true;
				}
			}

			key = null;
			return false;
		}
		async Task<JsonWebKey> KeyExpirationHelper( JsonWebKey key ) {
			if( key == null ) {
				return null;
			}

			if( key.ExpiresAt == null ) {
				throw new InvalidOperationException( "Stored public keys need expiry info" );
			}

			TimeSpan dt = key.ExpiresAt.Value - DateTime.UtcNow;

			if( dt < TimeSpan.FromSeconds( 0 ) ) {
				await ( this as IPublicKeyDataProvider )
					.DeleteAsync( key.Id )
					.SafeAsync();
				return null;
			}

			return key;
		}
Ejemplo n.º 3
0
 public IAccount FindByPublicKey(JsonWebKey publicKey)
 {
     return(Items.FirstOrDefault(o => o.Key.Equals(publicKey)));
 }
Ejemplo n.º 4
0
        public void Create(JsonWebKey jwk, Type clientType)
        {
            ICryptographyProvider client = LocalCryptographyProviderFactory.Create(jwk);

            Assert.IsInstanceOf(clientType, client, "Key {0} of type {1} did not yield client type {2}", jwk.Id, jwk.KeyType, clientType.Name);
        }
Ejemplo n.º 5
0
 public string Decrypt(string payload, JsonWebKey jsonWebKey, string password)
 {
     return(InternalDecrypt(payload, jsonWebKey, Encoding.UTF8.GetBytes(password)));
 }
Ejemplo n.º 6
0
 public string Build(string payload, string alg, string enc, JsonWebKey jsonWebKey, string password)
 {
     return(InternalBuild(payload, alg, enc, jsonWebKey, Encoding.UTF8.GetBytes(password)));
 }
Ejemplo n.º 7
0
        public async Task <IActionResult> Add(JsonWebKey jsonWebKey, CancellationToken cancellationToken)
        {
            var result = await _jwksStore.Add(jsonWebKey, cancellationToken).ConfigureAwait(false);

            return(result ? Ok() : (IActionResult)BadRequest());
        }
Ejemplo n.º 8
0
 internal PolicyCertificateModification(JsonWebKey internalPolicyCertificate)
 {
     InternalPolicyCertificate = internalPolicyCertificate;
 }
 public JsonWebKey FixupKey(JsonWebKey key)
 {
     byte[] existing = Base64UrlEncoder.DecodeBytes(key.N);
     TrimKey(key, existing);
     return(key);
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Verifies web keys are equal
 /// </summary>
 /// <param name="webKey1"> first web key </param>
 /// <param name="webKey2"> second web key </param>
 private void VerifyWebKeysAreEqual(JsonWebKey webKey1, JsonWebKey webKey2)
 {
     Assert.True(webKey1.Equals(webKey2));
     Assert.Equal(webKey1.Kid, webKey2.Kid);
     Assert.Equal(webKey1.Kty, webKey2.Kty);
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Converts a JWK to RSA.
 /// </summary>
 public static RSA ToRsa(this JsonWebKey jwk, bool includePrivateParameters = false)
 {
     return(RSA.Create(jwk.ToRsaParameters(includePrivateParameters)));
 }
Ejemplo n.º 12
0
        /// <summary>
        /// Encrypt Async
        /// </summary>
        /// <param name="value">The value to encrypt as JWE string</param>
        /// <returns>JWE string</returns>
        public async Task <string> EncryptAsync(string value)
        {
            JsonWebKey publicJsonWebKey = null;

            try
            {
                publicJsonWebKey = await this.keyResolver.GetEncryptionKeyAsync();

                if (publicJsonWebKey == null)
                {
                    throw new EncryptionException(string.Format("Encryption key not found by KeyResolver."));
                }

                var encodedJwe   = string.Empty;
                var extraHeaders = new Dictionary <string, object>
                {
                    { "kid", publicJsonWebKey.Kid },
                    { "kty", publicJsonWebKey.Kty }
                };
                if (publicJsonWebKey.Kty == "EC")
                {
                    var xByteArray = Jose.Base64Url.Decode(publicJsonWebKey.X);
                    var yByteArray = Jose.Base64Url.Decode(publicJsonWebKey.Y);
                    var eccKey     = EccKey.New(xByteArray, yByteArray, null, CngKeyUsages.KeyAgreement);
                    encodedJwe = Jose.JWT.Encode(value, eccKey, Jose.JweAlgorithm.ECDH_ES_A256KW, Jose.JweEncryption.A256GCM, null, extraHeaders, null);
                }
                else if (publicJsonWebKey.Kty == "RSA")
                {
                    var keyParams = new RSAParameters
                    {
                        Exponent = Jose.Base64Url.Decode(publicJsonWebKey.E),
                        Modulus  = Jose.Base64Url.Decode(publicJsonWebKey.N)
                    };
                    var rsa = RSA.Create();
                    rsa.ImportParameters(keyParams);
                    encodedJwe = Jose.JWT.Encode(value, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM, null, extraHeaders, null);
                }
                else
                {
                    throw new EncryptionException("Unsupport Json Web Key type.");
                }

                logger.LogDebug("Encrypting data with keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty);

                return(Constants.CIPHER_HEADER + encodedJwe);
            }
            catch (Jose.EncryptionException iaEx)
            {
                if (publicJsonWebKey == null)
                {
                    logger.LogError(iaEx, "An Encryption Exceptionn occurred.");
                }
                else
                {
                    logger.LogError(iaEx, "An Encryption Exceptionn occurred. keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty);
                }

                throw new EncryptionException("Unable to decrypt data.", iaEx);
            }
            catch (Jose.InvalidAlgorithmException iaEx)
            {
                if (publicJsonWebKey == null)
                {
                    logger.LogError(iaEx, "An Invalid Algorithm Exception occurred.");
                }
                else
                {
                    logger.LogError(iaEx, "An Invalid Algorithm Exception occurred. keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty);
                }

                throw new EncryptionException("Unable to decrypt data.", iaEx);
            }
            catch (EncryptionException eeEx)
            {
                if (publicJsonWebKey == null)
                {
                    logger.LogError(eeEx, "An Encryption Exception Occurred: Value: {0}", value);
                }
                else
                {
                    logger.LogError(eeEx, "An Encryption Exception Occurred: Keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty);
                }

                throw;
            }
            catch (Exception ex)
            {
                if (ex.GetType() == typeof(NotImplementedException))
                {
                    throw;
                }
                else
                {
                    logger.LogError(ex, "An Exception Occurred: Keyid: {0}, type: {1}", publicJsonWebKey.Kid, publicJsonWebKey.Kty);
                    throw new EncryptionException("Unable to encrypt data.", ex);
                }
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Decrypt Async
        /// </summary>
        /// <param name="cipher">Cipher string</param>
        /// <returns>Descrypted string</returns>
        public async Task <string> DecryptAsync(string cipher)
        {
            var privateJsonWebKey = default(JsonWebKey);

            try
            {
                if (string.IsNullOrEmpty(cipher) ||
                    !cipher.StartsWith(Constants.CIPHER_HEADER, StringComparison.Ordinal))
                {
                    throw new InvalidHeaderException("Invalid encryption header.");
                }

                var value = default(string);
                var requestedprivateJsonWebKey = default(JsonWebKey);
                try
                {
                    cipher = cipher.Substring(Constants.CIPHER_HEADER.Length);
                    var cipherArray = cipher.Split(new char[] { '.' });
                    var json        = Encoding.UTF8.GetString(Jose.Base64Url.Decode(cipherArray[0]));
                    requestedprivateJsonWebKey = new JsonWebKey(json);
                }
                catch (ArgumentNullException anEx)
                {
                    throw new SerializerException("Unable to deserializer value.", anEx);
                }
                catch (ArgumentException aEx)
                {
                    throw new SerializerException("Unable to deserializer value.", aEx);
                }

                privateJsonWebKey = await this.keyResolver.GetDecryptionKeyAsync(requestedprivateJsonWebKey.Kid);

                if (privateJsonWebKey == null)
                {
                    throw new EncryptionException(string.Format("Decryption key not found. ID: '{0}'.", requestedprivateJsonWebKey.Kid));
                }

                if (privateJsonWebKey.Kty == "EC")
                {
                    var xByteArray = Jose.Base64Url.Decode(privateJsonWebKey.X);
                    var yByteArray = Jose.Base64Url.Decode(privateJsonWebKey.Y);
                    var dByteArray = Jose.Base64Url.Decode(privateJsonWebKey.D);
                    var privateKey = EccKey.New(xByteArray, yByteArray, dByteArray, CngKeyUsages.KeyAgreement);
                    value = Jose.JWT.Decode(cipher, privateKey);
                }
                else if (privateJsonWebKey.Kty == "RSA")
                {
                    var keyParams = new RSAParameters
                    {
                        Exponent = Jose.Base64Url.Decode(privateJsonWebKey.E),
                        Modulus  = Jose.Base64Url.Decode(privateJsonWebKey.N),
                        P        = Jose.Base64Url.Decode(privateJsonWebKey.P),
                        Q        = Jose.Base64Url.Decode(privateJsonWebKey.Q),
                        D        = Jose.Base64Url.Decode(privateJsonWebKey.D),
                        InverseQ = Jose.Base64Url.Decode(privateJsonWebKey.QI),
                        DP       = Jose.Base64Url.Decode(privateJsonWebKey.DQ),
                        DQ       = Jose.Base64Url.Decode(privateJsonWebKey.DP)
                    };

                    var rsa = RSA.Create();
                    rsa.ImportParameters(keyParams);
                    value = Jose.JWT.Decode(cipher, rsa, Jose.JweAlgorithm.RSA_OAEP_256, Jose.JweEncryption.A256GCM);
                }
                else
                {
                    throw new EncryptionException("Unsupport Json Web Key type.");
                }

                logger.LogDebug("Decrypted data with keyid: {0}, type: {1}, value: {2}", privateJsonWebKey.Kid, privateJsonWebKey.Kty, value);

                return(value);
            }
            catch (Jose.EncryptionException iaEx)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(iaEx, "An Encryption Exceptionn occurred.");
                }
                else
                {
                    logger.LogError(iaEx, "An Encryption Exceptionn occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw new EncryptionException("Unable to decrypt data.", iaEx);
            }
            catch (Jose.InvalidAlgorithmException iaEx)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(iaEx, "An Invalid Algorithm Exception occurred.");
                }
                else
                {
                    logger.LogError(iaEx, "An Invalid Algorithm Exception occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw new EncryptionException("Unable to decrypt data.", iaEx);
            }
            catch (InvalidHeaderException ihEx)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(ihEx, "An Invalid Header Exception occurred.");
                }
                else
                {
                    logger.LogError(ihEx, "An Invalid Header Exception occurred. keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw;
            }
            catch (SerializerException sEx)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(sEx.InnerException, "Unable to deserializer value.");
                }
                else
                {
                    logger.LogError(sEx, "Unable to deserializer value.: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw;
            }
            catch (EncryptionException eEx)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(eEx, "An Decryption Exception Occurred");
                }
                else
                {
                    logger.LogError(eEx, "An Decryption Exception Occurred: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw;
            }
            catch (Exception ex)
            {
                if (privateJsonWebKey == null)
                {
                    logger.LogError(ex, "An Decryption Exception Occurred");
                }
                else
                {
                    logger.LogError(ex, "An Exception Occurred: Keyid: {0}, type: {1}", privateJsonWebKey.Kid, privateJsonWebKey.Kty);
                }

                throw new EncryptionException("Unable to decrypt data.", ex);
            }
        }
		private void AddKeyToDb( JsonWebKey key ) {
			m_allTheKeys.Add( key );
			m_mockPublicKeyDataProvider
				.Setup( pkdp => pkdp.GetByIdAsync( key.Id ) )
				.ReturnsAsync( key );
		}
        public void SignReturnsNullOnUnsupported()
        {
            JsonWebKey jwk = KeyModelFactory.JsonWebKey(KeyType.Ec, curveName: "invalid", keyOps: new[] { KeyOperation.Sign });

            EcCryptographyProvider client = new EcCryptographyProvider(jwk, null);
            SignResult             result = client.Sign(default, new byte[] { 0xff }, default);
		Task IPublicKeyDataProvider.SaveAsync( JsonWebKey key ) {
			return m_inner.SaveAsync( key );
		}
Ejemplo n.º 17
0
        /// <summary>
        /// Validate the signature and returns the JWSPayLoad.
        /// </summary>
        /// <param name="jws"></param>
        /// <param name="jsonWebKey"></param>
        /// <returns></returns>
        public JwsPayload ValidateSignature(string jws, JsonWebKey jsonWebKey)
        {
            if (string.IsNullOrWhiteSpace(jws))
            {
                throw new ArgumentNullException(nameof(jws));
            }

            if (jsonWebKey == null)
            {
                throw new ArgumentNullException(nameof(jsonWebKey));
            }

            var parts = GetParts(jws);

            if (!parts.Any())
            {
                return(null);
            }

            var base64EncodedProtectedHeader      = parts[0];
            var base64EncodedSerialized           = parts[1];
            var combinedProtectedHeaderAndPayLoad = string.Format("{0}.{1}", base64EncodedProtectedHeader,
                                                                  base64EncodedSerialized);
            var    serializedProtectedHeader = base64EncodedProtectedHeader.Base64Decode();
            var    serializedPayload         = base64EncodedSerialized.Base64Decode();
            var    signature       = parts[2].Base64DecodeBytes();
            var    protectedHeader = JsonConvert.DeserializeObject <JwsProtectedHeader>(serializedProtectedHeader);
            JwsAlg jwsAlg;

            if (!Enum.TryParse(protectedHeader.Alg, out jwsAlg))
            {
                return(null);
            }

            var signatureIsCorrect = false;

            switch (jsonWebKey.Kty)
            {
            case KeyType.RSA:
                // To validate we need the parameters : modulus & exponent.
                signatureIsCorrect = _createJwsSignature.VerifyWithRsa(
                    jwsAlg,
                    jsonWebKey.SerializedKey,
                    combinedProtectedHeaderAndPayLoad,
                    signature);
                break;

#if NET46 || NET45
            case KeyType.EC:
                signatureIsCorrect = _createJwsSignature.VerifyWithEllipticCurve(
                    jsonWebKey.SerializedKey,
                    combinedProtectedHeaderAndPayLoad,
                    signature);
                break;
#endif
            }

            if (!signatureIsCorrect)
            {
                return(null);
            }

            return(JsonConvert.DeserializeObject <JwsPayload>(serializedPayload));
        }
Ejemplo n.º 18
0
        public string Sign(JwsPayload jwsPayload, JsonWebKey jsonWebKey)
        {
            var serializedPayload = JsonConvert.SerializeObject(jwsPayload);

            return(_jwsGenerator.Build(serializedPayload, jsonWebKey.Alg, jsonWebKey));
        }
Ejemplo n.º 19
0
 internal AttestationResult(string internalJti, string internalIss, double?internalIat, double?internalExp, double?internalNbf, object internalCnf, string nonce, string version, object runtimeClaims, object inittimeClaims, object policyClaims, string verifierType, JsonWebKey internalPolicySigner, string internalPolicyHash, bool?isDebuggable, float?productId, string mrEnclave, string mrSigner, float?svn, string internalEnclaveHeldData, object sgxCollateral, string internalDeprecatedVersion, bool?internalDeprecatedIsDebuggable, object internalDeprecatedSgxCollateral, string internalDeprecatedEnclaveHeldData, string internalDeprecatedEnclaveHeldData2, float?internalDeprecatedProductId, string internalDeprecatedMrEnclave, string internalDeprecatedMrSigner, float?internalDeprecatedSvn, string internalDeprecatedTee, JsonWebKey internalDeprecatedPolicySigner, string internalDeprecatedPolicyHash, string internalDeprecatedRpData)
 {
     InternalJti          = internalJti;
     InternalIss          = internalIss;
     InternalIat          = internalIat;
     InternalExp          = internalExp;
     InternalNbf          = internalNbf;
     InternalCnf          = internalCnf;
     Nonce                = nonce;
     Version              = version;
     RuntimeClaims        = runtimeClaims;
     InittimeClaims       = inittimeClaims;
     PolicyClaims         = policyClaims;
     VerifierType         = verifierType;
     InternalPolicySigner = internalPolicySigner;
     InternalPolicyHash   = internalPolicyHash;
     IsDebuggable         = isDebuggable;
     ProductId            = productId;
     MrEnclave            = mrEnclave;
     MrSigner             = mrSigner;
     Svn = svn;
     InternalEnclaveHeldData            = internalEnclaveHeldData;
     SgxCollateral                      = sgxCollateral;
     InternalDeprecatedVersion          = internalDeprecatedVersion;
     InternalDeprecatedIsDebuggable     = internalDeprecatedIsDebuggable;
     InternalDeprecatedSgxCollateral    = internalDeprecatedSgxCollateral;
     InternalDeprecatedEnclaveHeldData  = internalDeprecatedEnclaveHeldData;
     InternalDeprecatedEnclaveHeldData2 = internalDeprecatedEnclaveHeldData2;
     InternalDeprecatedProductId        = internalDeprecatedProductId;
     InternalDeprecatedMrEnclave        = internalDeprecatedMrEnclave;
     InternalDeprecatedMrSigner         = internalDeprecatedMrSigner;
     InternalDeprecatedSvn              = internalDeprecatedSvn;
     InternalDeprecatedTee              = internalDeprecatedTee;
     InternalDeprecatedPolicySigner     = internalDeprecatedPolicySigner;
     InternalDeprecatedPolicyHash       = internalDeprecatedPolicyHash;
     InternalDeprecatedRpData           = internalDeprecatedRpData;
 }
Ejemplo n.º 20
0
 public Task <bool> Update(JsonWebKey data, CancellationToken token)
 {
     _dbContext.JsonWebKeys.Update(data);
     return(Task.FromResult(true));
 }
        /// <summary>
        /// Creates a signature from a digest using the specified key in the vault
        /// </summary>
        /// <param name="key"> The web key of the signing key </param>
        /// <param name="algorithm"> the signing algorithm </param>
        /// <param name="digest"> the signing digest hash value </param>
        /// <returns> signature </returns>
        public static async Task <KeyOperationResult> SignAsync(this KeyVaultClient client, JsonWebKey key, string algorithm, byte[] digest)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            return(await client.SignAsync(key.Kid, algorithm, digest).ConfigureAwait(false));
        }
Ejemplo n.º 22
0
 public string Build(string payload, string alg, string enc, JsonWebKey jsonWebKey)
 {
     return(InternalBuild(payload, alg, enc, jsonWebKey));
 }
        /// <summary>
        /// Wraps a symmetric key using the specified wrapping key and algorithm.
        /// </summary>
        /// <param name="wrappingKey">The wrapping key</param>
        /// <param name="key">The key to wrap</param>
        /// <param name="algorithm">The algorithm to use</param>
        /// <returns>The wrapped key</returns>
        public static async Task <KeyOperationResult> WrapKeyAsync(this KeyVaultClient client, JsonWebKey wrappingKey, byte[] key, string algorithm)
        {
            KeyOperationResult result = null;

            if (wrappingKey == null)
            {
                throw new ArgumentNullException("wrappingKey");
            }

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            return(await client.WrapKeyAsync(wrappingKey.Kid, algorithm, key).ConfigureAwait(false));
        }
Ejemplo n.º 24
0
 public string Decrypt(string payload, JsonWebKey jsonWebKey)
 {
     return(InternalDecrypt(payload, jsonWebKey));
 }
        /// <summary>
        /// Decrypts a single block of encrypted data
        /// </summary>
        /// <param name="key">The web key to use for decryption</param>
        /// <param name="algorithm">The encryption algorithm</param>
        /// <param name="cipherText">The encrypted data</param>
        /// <returns></returns>
        public static async Task <KeyOperationResult> DecryptDataAsync(this KeyVaultClient client, JsonWebKey key, string algorithm, byte[] cipherText)
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            return(await client.DecryptAsync(key.Kid, algorithm, cipherText).ConfigureAwait(false));
        }
        public KeyBundle ImportKey(string vaultName, string keyName, KeyAttributes keyAttributes, JsonWebKey webKey, bool?importToHsm)
        {
            if (string.IsNullOrEmpty(vaultName))
            {
                throw new ArgumentNullException("vaultName");
            }
            if (string.IsNullOrEmpty(keyName))
            {
                throw new ArgumentNullException("keyName");
            }
            if (keyAttributes == null)
            {
                throw new ArgumentNullException("keyAttributes");
            }
            if (webKey == null)
            {
                throw new ArgumentNullException("webKey");
            }
            if (webKey.Kty == JsonWebKeyType.RsaHsm && (importToHsm.HasValue && !importToHsm.Value))
            {
                throw new ArgumentException(KeyVaultProperties.Resources.ImportByokAsSoftkeyError);
            }

            string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);

            webKey.KeyOps = keyAttributes.KeyOps;
            var keyBundle = new Azure.KeyVault.Models.KeyBundle()
            {
                Attributes = (Azure.KeyVault.Models.KeyAttributes)keyAttributes,
                Key        = webKey,
                Tags       = keyAttributes.TagsDirectionary
            };

            try
            {
                keyBundle = this.keyVaultClient.ImportKeyAsync(vaultAddress, keyName, keyBundle, importToHsm).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                throw GetInnerException(ex);
            }

            return(new KeyBundle(keyBundle, this.vaultUriHelper));
        }
        /// <summary>
        /// Encrypts a single block of data. The amount of data that may be encrypted is determined
        /// by the target key type and the encryption algorithm, e.g. RSA, RSA_OAEP
        /// </summary>
        /// <param name="key">The web key to use for encryption</param>
        /// <param name="algorithm">The encryption algorithm</param>
        /// <param name="plaintext">The plain text to encrypt</param>
        /// <returns></returns>
        public static async Task <KeyOperationResult> EncryptDataAsync(this KeyVaultClient client, JsonWebKey key, string algorithm, byte[] plaintext)
        {
            KeyOperationResult result = null;

            if (key == null)
            {
                throw new ArgumentNullException("key");
            }

            if (string.IsNullOrEmpty(algorithm))
            {
                throw new ArgumentNullException("algorithm");
            }

            if (plaintext == null)
            {
                throw new ArgumentNullException("plaintext");
            }

            return(await client.EncryptAsync(key.Kid, algorithm, plaintext).ConfigureAwait(false));
        }
        public void Defaults()
        {
            var        context    = new CompareContext();
            JsonWebKey jsonWebKey = new JsonWebKey();

            if (jsonWebKey.Alg != null)
            {
                context.Diffs.Add("jsonWebKey.Alg != null");
            }

            if (jsonWebKey.KeyOps.Count != 0)
            {
                context.Diffs.Add("jsonWebKey.KeyOps.Count != 0");
            }

            if (jsonWebKey.Kid != null)
            {
                context.Diffs.Add("jsonWebKey.Kid != null");
            }

            if (jsonWebKey.Kty != null)
            {
                context.Diffs.Add("jsonWebKey.Kty != null");
            }

            if (jsonWebKey.X5c == null)
            {
                context.Diffs.Add("jsonWebKey.X5c == null");
            }

            if (jsonWebKey.X5c.Count != 0)
            {
                context.Diffs.Add("jsonWebKey.X5c.Count != 0");
            }

            if (jsonWebKey.X5t != null)
            {
                context.Diffs.Add("jsonWebKey.X5t != null");
            }

            if (jsonWebKey.X5u != null)
            {
                context.Diffs.Add("jsonWebKey.X5u != null");
            }

            if (jsonWebKey.Use != null)
            {
                context.Diffs.Add("jsonWebKey.Use != null");
            }

            if (jsonWebKey.AdditionalData == null)
            {
                context.Diffs.Add("jsonWebKey.AdditionalData == null");
            }
            else if (jsonWebKey.AdditionalData.Count != 0)
            {
                context.Diffs.Add("jsonWebKey.AdditionalData.Count != 0");
            }

            TestUtilities.AssertFailIfErrors(context);
        }
Ejemplo n.º 29
0
        private static IEnumerable <JsonWebKey> ExtractJsonWebKeys(Table table)
        {
            var builder = new JsonWebKeyBuilder();
            var jwks    = new List <JsonWebKey>();

            foreach (var record in table.Rows)
            {
                var        type    = record["Type"];
                var        kid     = record["Kid"];
                var        algName = record["AlgName"];
                JsonWebKey jwk     = null;
                switch (type)
                {
                case "SIG":
                    if (algName.StartsWith("ES"))
                    {
                        using (var ec = new ECDsaCng())
                        {
                            jwk = builder.NewSign(kid, new[]
                            {
                                KeyOperations.Sign,
                                KeyOperations.Verify
                            }).SetAlg(ec, algName).Build();
                        }
                    }
                    else if (algName.StartsWith("HS"))
                    {
                        using (var hmac = new HMACSHA256())
                        {
                            jwk = builder.NewSign(kid, new[]
                            {
                                KeyOperations.Sign,
                                KeyOperations.Verify
                            }).SetAlg(hmac, algName).Build();
                        }
                    }
                    else
                    {
                        using (var rsa = RSA.Create())
                        {
                            jwk = builder.NewSign(kid, new[]
                            {
                                KeyOperations.Sign,
                                KeyOperations.Verify
                            }).SetAlg(rsa, algName).Build();
                        }
                    }
                    break;

                case "ENC":
                    using (var rsa = RSA.Create())
                    {
                        jwk = builder.NewEnc(kid, new[]
                        {
                            KeyOperations.Encrypt,
                            KeyOperations.Decrypt
                        }).SetAlg(rsa, algName).Build();
                    }
                    break;
                }

                jwks.Add(jwk);
            }

            return(jwks);
        }
Ejemplo n.º 30
0
        private async Task <bool> InvokeCryptographyEndpointAsync()
        {
            // Metadata requests must be made via GET.
            // See http://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest
            if (!string.Equals(Request.Method, "GET", StringComparison.OrdinalIgnoreCase))
            {
                Logger.LogError("The cryptography request was rejected because an invalid " +
                                "HTTP method was specified: {Method}.", Request.Method);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = "The specified HTTP method is not valid."
                }));
            }

            var request = new OpenIdConnectRequest(Request.Query);

            // Note: set the message type before invoking the ExtractCryptographyRequest event.
            request.SetProperty(OpenIdConnectConstants.Properties.MessageType,
                                OpenIdConnectConstants.MessageTypes.CryptographyRequest);

            // Store the cryptography request in the OWIN context.
            Context.SetOpenIdConnectRequest(request);

            var @event = new ExtractCryptographyRequestContext(Context, Options, request);
            await Options.Provider.ExtractCryptographyRequest(@event);

            if (@event.HandledResponse)
            {
                Logger.LogDebug("The cryptography request was handled in user code.");

                return(true);
            }

            else if (@event.Skipped)
            {
                Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                return(false);
            }

            else if (@event.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ @event.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ @event.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = @event.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = @event.ErrorDescription,
                    ErrorUri = @event.ErrorUri
                }));
            }

            Logger.LogInformation("The cryptography request was successfully extracted " +
                                  "from the HTTP request: {Request}.", request);

            var context = new ValidateCryptographyRequestContext(Context, Options, request);
            await Options.Provider.ValidateCryptographyRequest(context);

            if (context.HandledResponse)
            {
                Logger.LogDebug("The cryptography request was handled in user code.");

                return(true);
            }

            else if (context.Skipped)
            {
                Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                return(false);
            }

            else if (context.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ context.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ context.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = context.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = context.ErrorDescription,
                    ErrorUri = context.ErrorUri
                }));
            }

            var notification = new HandleCryptographyRequestContext(Context, Options, request);

            foreach (var credentials in Options.SigningCredentials)
            {
                // If the signing key is not an asymmetric key, ignore it.
                if (!(credentials.Key is AsymmetricSecurityKey))
                {
                    Logger.LogDebug("A non-asymmetric signing key of type '{Type}' was excluded " +
                                    "from the key set.", credentials.Key.GetType().FullName);

                    continue;
                }

#if SUPPORTS_ECDSA
                if (!credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) &&
                    !credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512))
                {
                    Logger.LogInformation("An unsupported signing key of type '{Type}' was ignored and excluded " +
                                          "from the key set. Only RSA and ECDSA asymmetric security keys can be " +
                                          "exposed via the JWKS endpoint.", credentials.Key.GetType().Name);

                    continue;
                }
#else
                if (!credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256))
                {
                    Logger.LogInformation("An unsupported signing key of type '{Type}' was ignored and excluded " +
                                          "from the key set. Only RSA asymmetric security keys can be exposed " +
                                          "via the JWKS endpoint.", credentials.Key.GetType().Name);

                    continue;
                }
#endif

                var key = new JsonWebKey
                {
                    Use = JsonWebKeyUseNames.Sig,

                    // Resolve the JWA identifier from the algorithm specified in the credentials.
                    Alg = OpenIdConnectServerHelpers.GetJwtAlgorithm(credentials.Algorithm),

                    // Use the key identifier specified in the signing credentials.
                    Kid = credentials.Kid,
                };

                if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.RsaSha256))
                {
                    RSA algorithm = null;

                    // Note: IdentityModel 5 doesn't expose a method allowing to retrieve the underlying algorithm
                    // from a generic asymmetric security key. To work around this limitation, try to cast
                    // the security key to the built-in IdentityModel types to extract the required RSA instance.
                    // See https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/395
                    if (credentials.Key is X509SecurityKey x509SecurityKey)
                    {
                        algorithm = x509SecurityKey.PublicKey as RSA;
                    }

                    else if (credentials.Key is RsaSecurityKey rsaSecurityKey)
                    {
                        algorithm = rsaSecurityKey.Rsa;

                        // If no RSA instance can be found, create one using
                        // the RSA parameters attached to the security key.
                        if (algorithm == null)
                        {
                            var rsa = RSA.Create();
                            rsa.ImportParameters(rsaSecurityKey.Parameters);
                            algorithm = rsa;
                        }
                    }

                    // Skip the key if an algorithm instance cannot be extracted.
                    if (algorithm == null)
                    {
                        Logger.LogWarning("A signing key was ignored because it was unable " +
                                          "to provide the requested algorithm instance.");

                        continue;
                    }

                    // Export the RSA public key to create a new JSON Web Key
                    // exposing the exponent and the modulus parameters.
                    var parameters = algorithm.ExportParameters(includePrivateParameters: false);

                    Debug.Assert(parameters.Exponent != null &&
                                 parameters.Modulus != null,
                                 "RSA.ExportParameters() shouldn't return null parameters.");

                    key.Kty = JsonWebAlgorithmsKeyTypes.RSA;

                    // Note: both E and N must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7518#section-6.3.1.1
                    key.E = Base64UrlEncoder.Encode(parameters.Exponent);
                    key.N = Base64UrlEncoder.Encode(parameters.Modulus);
                }

#if SUPPORTS_ECDSA
                else if (credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha256) ||
                         credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha384) ||
                         credentials.Key.IsSupportedAlgorithm(SecurityAlgorithms.EcdsaSha512))
                {
                    ECDsa algorithm = null;

                    if (credentials.Key is X509SecurityKey x509SecurityKey)
                    {
                        algorithm = x509SecurityKey.PublicKey as ECDsa;
                    }

                    else if (credentials.Key is ECDsaSecurityKey ecdsaSecurityKey)
                    {
                        algorithm = ecdsaSecurityKey.ECDsa;
                    }

                    // Skip the key if an algorithm instance cannot be extracted.
                    if (algorithm == null)
                    {
                        Logger.LogWarning("A signing key was ignored because it was unable " +
                                          "to provide the requested algorithm instance.");

                        continue;
                    }

                    // Export the ECDsa public key to create a new JSON Web Key
                    // exposing the coordinates of the point on the curve.
                    var parameters = algorithm.ExportParameters(includePrivateParameters: false);

                    Debug.Assert(parameters.Q.X != null &&
                                 parameters.Q.Y != null,
                                 "ECDsa.ExportParameters() shouldn't return null coordinates.");

                    key.Kty = JsonWebAlgorithmsKeyTypes.EllipticCurve;
                    key.Crv = OpenIdConnectServerHelpers.GetJwtAlgorithmCurve(parameters.Curve);

                    // Note: both X and Y must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7518#section-6.2.1.2
                    key.X = Base64UrlEncoder.Encode(parameters.Q.X);
                    key.Y = Base64UrlEncoder.Encode(parameters.Q.Y);
                }
#endif

                // If the signing key is embedded in a X.509 certificate, set
                // the x5t and x5c parameters using the certificate details.
                var certificate = (credentials.Key as X509SecurityKey)?.Certificate;
                if (certificate != null)
                {
                    // x5t must be base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7517#section-4.8
                    key.X5t = Base64UrlEncoder.Encode(certificate.GetCertHash());

                    // Unlike E or N, the certificates contained in x5c
                    // must be base64-encoded and not base64url-encoded.
                    // See https://tools.ietf.org/html/rfc7517#section-4.7
                    key.X5c.Add(Convert.ToBase64String(certificate.RawData));
                }

                notification.Keys.Add(key);
            }

            await Options.Provider.HandleCryptographyRequest(notification);

            if (notification.HandledResponse)
            {
                Logger.LogDebug("The cryptography request was handled in user code.");

                return(true);
            }

            else if (notification.Skipped)
            {
                Logger.LogDebug("The default cryptography request handling was skipped from user code.");

                return(false);
            }

            else if (notification.IsRejected)
            {
                Logger.LogError("The cryptography request was rejected with the following error: {Error} ; {Description}",
                                /* Error: */ notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                                /* Description: */ notification.ErrorDescription);

                return(await SendCryptographyResponseAsync(new OpenIdConnectResponse
                {
                    Error = notification.Error ?? OpenIdConnectConstants.Errors.InvalidRequest,
                    ErrorDescription = notification.ErrorDescription,
                    ErrorUri = notification.ErrorUri
                }));
            }

            var keys = new JArray();

            foreach (var key in notification.Keys)
            {
                var item = new JObject();

                // Ensure a key type has been provided.
                // See https://tools.ietf.org/html/rfc7517#section-4.1
                if (string.IsNullOrEmpty(key.Kty))
                {
                    Logger.LogError("A JSON Web Key was excluded from the key set because " +
                                    "it didn't contain the mandatory 'kid' parameter.");

                    continue;
                }

                // Create a dictionary associating the
                // JsonWebKey components with their values.
                var parameters = new Dictionary <string, string>
                {
                    [JsonWebKeyParameterNames.Kid] = key.Kid,
                    [JsonWebKeyParameterNames.Use] = key.Use,
                    [JsonWebKeyParameterNames.Kty] = key.Kty,
                    [JsonWebKeyParameterNames.Alg] = key.Alg,
                    [JsonWebKeyParameterNames.Crv] = key.Crv,
                    [JsonWebKeyParameterNames.E]   = key.E,
                    [JsonWebKeyParameterNames.N]   = key.N,
                    [JsonWebKeyParameterNames.X]   = key.X,
                    [JsonWebKeyParameterNames.Y]   = key.Y,
                    [JsonWebKeyParameterNames.X5t] = key.X5t,
                    [JsonWebKeyParameterNames.X5u] = key.X5u
                };

                foreach (var parameter in parameters)
                {
                    if (!string.IsNullOrEmpty(parameter.Value))
                    {
                        item.Add(parameter.Key, parameter.Value);
                    }
                }

                if (key.KeyOps.Count != 0)
                {
                    item.Add(JsonWebKeyParameterNames.KeyOps, new JArray(key.KeyOps));
                }

                if (key.X5c.Count != 0)
                {
                    item.Add(JsonWebKeyParameterNames.X5c, new JArray(key.X5c));
                }

                keys.Add(item);
            }

            // Note: AddParameter() is used here to ensure the mandatory "keys" node
            // is returned to the caller, even if the key set doesn't expose any key.
            // See https://tools.ietf.org/html/rfc7517#section-5 for more information.
            var response = new OpenIdConnectResponse();
            response.AddParameter(OpenIdConnectConstants.Parameters.Keys, keys);

            return(await SendCryptographyResponseAsync(response));
        }
Ejemplo n.º 31
0
        public KeyBundle ImportKey(string vaultName, string keyName, KeyAttributes keyAttributes, JsonWebKey webKey, bool?importToHsm)
        {
            if (string.IsNullOrEmpty(vaultName))
            {
                throw new ArgumentNullException("vaultName");
            }
            if (string.IsNullOrEmpty(keyName))
            {
                throw new ArgumentNullException("keyName");
            }
            if (keyAttributes == null)
            {
                throw new ArgumentNullException("keyAttributes");
            }
            if (webKey == null)
            {
                throw new ArgumentNullException("webKey");
            }

            string vaultAddress = this.vaultUriHelper.CreateVaultAddress(vaultName);

            Client.KeyAttributes clientAttributes = (Client.KeyAttributes)keyAttributes;

            webKey.KeyOps = keyAttributes.KeyOps;
            Client.KeyBundle clientKeyBundle = new Client.KeyBundle()
            {
                Attributes = clientAttributes,
                Key        = webKey
            };

            try
            {
                clientKeyBundle = this.keyVaultClient.ImportKeyAsync(vaultAddress, keyName, clientKeyBundle, importToHsm).GetAwaiter().GetResult();
            }
            catch (Exception ex)
            {
                throw GetInnerException(ex);
            }

            return(new KeyBundle(clientKeyBundle, this.vaultUriHelper));
        }
Ejemplo n.º 32
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LocalCryptographyClient"/> class.
        /// </summary>
        /// <param name="jsonWebKey">A <see cref="JsonWebKey"/> used for cryptographic operations.</param>
        /// <exception cref="ArgumentNullException"><paramref name="jsonWebKey"/> is null.</exception>
        /// <exception cref="NotSupportedException">The <paramref name="jsonWebKey"/> has a <see cref="JsonWebKey.KeyType"/> that is not supported.</exception>
#pragma warning disable AZC0007 // DO provide a minimal constructor that takes only the parameters required to connect to the service.
        public LocalCryptographyClient(JsonWebKey jsonWebKey)
        {
            _jsonWebKey = jsonWebKey ?? throw new ArgumentNullException(nameof(jsonWebKey));
            _provider   = LocalCryptographyProviderFactory.Create(jsonWebKey, null) ?? throw new NotSupportedException(@$ "Key type " "{jsonWebKey.KeyType}" " is not supported");
        }
Ejemplo n.º 33
0
 internal PolicyResult(PolicyModification policyResolution, string basePolicyTokenHash, JsonWebKey basePolicySigner, string basePolicy)
 {
     PolicyResolution    = policyResolution;
     BasePolicyTokenHash = basePolicyTokenHash;
     BasePolicySigner    = basePolicySigner;
     BasePolicy          = basePolicy;
 }
Ejemplo n.º 34
0
    /// <summary>
    /// Converts a JSON web key to a URL safe string.
    /// </summary>
    /// <param name="key">The key.</param>
    /// <returns></returns>
    public static string ToJwkString(this JsonWebKey key)
    {
        var json = JsonSerializer.Serialize(key);

        return(Base64Url.Encode(Encoding.UTF8.GetBytes(json)));
    }
		Task IPublicKeyDataProvider.SaveAsync( JsonWebKey key ) {
			if( !m_keys.TryAdd( key.Id, key ) ) {
				throw new InvalidOperationException( "Attempted to add a key twice" );
			}
			return Task.Delay( 0 );
		}