public bool SubmitResponse(SignatureMessage message)
        {
            bool retval = false;

            try
            {
                // Use the public key hint to identify which public key to use.
                byte[] challenge;
                byte[] publicKey = DAL.Instance.GetPublicKeyForUser(message.UserId, message.PublicKeyHint, out challenge);

                CngKey pubCngKey = new SubjectPublicKeyInfo(publicKey).GetPublicKey();

                // Validate that the original challenge was signed using the corresponding private key.
                using (RSACng pubKey = new RSACng(pubCngKey))
                {
                    byte[] signature = Convert.FromBase64String(message.Signature);
                    retval = pubKey.VerifyData(challenge, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                }
            }
            catch (Exception)
            {
            }

            // Return a boolean response to the client
            // TODO:  What should actually be returned is an authentication token (OAuth or equivalent)
            // that the client uses for subsequent authentication requests
            return retval;
        }
Esempio n. 2
0
        private static void TestSignVerifyDataRoundTrip(byte[] message, HashAlgorithmName hashAlgorithm, RSASignaturePadding paddingMode, int expectedSignatureLength)
        {
            using (RSA rsa = new RSACng())
            {
                byte[] signature = rsa.SignData(message, hashAlgorithm, paddingMode);

                // RSACng.SignHash() is intentionally non-deterministic so we can verify that we got back a signature of the right length
                // but nothing about the contents.
                Assert.Equal(expectedSignatureLength, signature.Length);

                bool verified = rsa.VerifyData(message, signature, hashAlgorithm, paddingMode);
                Assert.True(verified);
            }
        }
        /// <summary>
        /// Verifies the given RSA PKCSv1.5 signature.
        /// </summary>
        /// <param name="dataToVerify"></param>
        /// <param name="signature"></param>
        /// <param name="rsaCngProvider">RSA CNG Provider.</param>
        /// <returns>true if signature is valid, false if it is not valid</returns>
        private bool RSAVerifySignature(byte[] dataToVerify, byte[] signature, RSACng rsaCngProvider)
        {
            Debug.Assert((dataToVerify != null) && (dataToVerify.Length != 0));
            Debug.Assert((signature != null) && (signature.Length != 0));
            Debug.Assert(rsaCngProvider != null);

            return rsaCngProvider.VerifyData(dataToVerify, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
        }
Esempio n. 4
0
        private static void TestSignAndVerifyDataFromStream(int messageSize)
        {
            RSASignaturePadding padding = RSASignaturePadding.Pkcs1;
            byte[] message = new byte[messageSize];
            byte b = 5;
            for (int i = 0; i < message.Length; i++)
            {
                message[i] = b;
                b = (byte)((b << 4) | (i & 0xf));
            }

            byte[] hash = SHA1.Create().ComputeHash(message);
            Stream stream = new MemoryStream(message);

            using (RSA rsa = new RSACng())
            {
                byte[] signature = rsa.SignData(stream, HashAlgorithmName.SHA1, padding);

                // Since the unique codepath being tested here is HashData(Stream...), the interesting test is to see if HashData(Stream...)
                // computed the right hash. The easiest way to test that is to compute the hash ourselves and call VerifyHash.
                bool verified = rsa.VerifyHash(hash, signature, HashAlgorithmName.SHA1, padding);
                Assert.True(verified);

                stream = new MemoryStream(message);
                verified = rsa.VerifyData(stream, signature, HashAlgorithmName.SHA1, padding);
                Assert.True(verified);
            }
        }
        public async Task<bool> SubmitResponse(SignatureMessage message)
        {
            bool retval = false;

            try
            {
                string challenge;
                JsonWebKey publicKey = _credentialService.GetPublicKeyForUser(message.UserId, message.PublicKeyHint, out challenge);

                var decodedClientData = message.ClientData.Rfc4648Base64UrlDecode();
                var decodedAuthnrData = message.AuthnrData.Rfc4648Base64UrlDecode();

                var clientDataJson = Encoding.UTF8.GetString(decodedClientData);
                var clientData = JsonConvert.DeserializeObject<ClientData>(clientDataJson);
                if (clientData.Challenge != challenge) return false;
                
                var sha256 = SHA256.Create();
                var hashedClientData = sha256.ComputeHash(decodedClientData);
                var buffer = new byte[decodedAuthnrData.Length + hashedClientData.Length];
                decodedAuthnrData.CopyTo(buffer, 0);
                hashedClientData.CopyTo(buffer, decodedAuthnrData.Length);

                var publicKeyInfo = new RSAParameters();
                publicKeyInfo.Modulus = publicKey.N.Rfc4648Base64UrlDecode();
                publicKeyInfo.Exponent = publicKey.E.Rfc4648Base64UrlDecode();
                var rsa = new RSACng();
                rsa.ImportParameters(publicKeyInfo);

                byte[] signature = message.Signature.Rfc4648Base64UrlDecode();
                retval = rsa.VerifyData(buffer, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                if (retval)
                {
                    var user = _signInService.FindBySubject(message.UserId);
                    await IssueCookie(user, "idsvr", "fido");
                }
            }
            catch (Exception)
            { }
            
            return retval;
        }