/// <summary> /// Tries to sign and verify a bit of test data using the given certificate. /// This will cause the security subsystem to grant the calling app access /// to the certificate's private key for the current session. /// /// </summary> /// <param name="selectedCertificate">The X.509 Certificate for which access is required</param> /// <returns>True on successful signing and verification, false otherwise.</returns> private static bool VerifyCertificateKeyAccess(Certificate selectedCertificate) { bool VerifyResult = false; // default to access failure var keyPairTask = PersistedKeyProvider.OpenKeyPairFromCertificateAsync( selectedCertificate, HashAlgorithmNames.Sha1, CryptographicPadding.RsaPkcs1V15).AsTask(); keyPairTask.Wait(); CryptographicKey keyPair = keyPairTask.Result; String buffer = "Data to sign"; IBuffer Data = CryptographicBuffer.ConvertStringToBinary(buffer, BinaryStringEncoding.Utf16BE); try { // sign the data by using the key var signedDataTask = CryptographicEngine.SignAsync(keyPair, Data).AsTask(); signedDataTask.Wait(); IBuffer Signed = signedDataTask.Result; VerifyResult = CryptographicEngine.VerifySignature(keyPair, Data, Signed); } catch (Exception exp) { Debug.WriteLine("Verification Failed. Exception Occurred : {0}", exp.Message); // default result is false so drop through to exit. } return(VerifyResult); }
public static async Task <string> CreateDeviceAuthChallengeResponseAsync(IDictionary <string, string> challengeData) { string authHeaderTemplate = "PKeyAuth {0}, Context=\"{1}\", Version=\"{2}\""; Certificate certificate = null; try { certificate = await FindCertificate(challengeData).ConfigureAwait(false); } catch (AdalException ex) { if (ex.ErrorCode == AdalError.DeviceCertificateNotFound) { return(await Task.FromResult(string.Format(CultureInfo.InvariantCulture, @"PKeyAuth Context=""{0}"",Version=""{1}""", challengeData["Context"], challengeData["Version"])).ConfigureAwait(false)); } } DeviceAuthJWTResponse response = new DeviceAuthJWTResponse(challengeData["SubmitUrl"], challengeData["nonce"], Convert.ToBase64String(certificate.GetCertificateBlob().ToArray())); IBuffer input = CryptographicBuffer.ConvertStringToBinary(response.GetResponseToSign(), BinaryStringEncoding.Utf8); CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15).AsTask().ConfigureAwait(false); IBuffer signed = await CryptographicEngine.SignAsync(keyPair, input).AsTask().ConfigureAwait(false); string signedJwt = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", response.GetResponseToSign(), Base64UrlEncoder.Encode(signed.ToArray())); string authToken = string.Format(CultureInfo.InvariantCulture, " AuthToken=\"{0}\"", signedJwt); return(string.Format(CultureInfo.InvariantCulture, authHeaderTemplate, authToken, challengeData["Context"], challengeData["Version"])); }
public static async Task <bool> VerifyCertificateKeyAccess(Certificate selectedCertificate) { bool VerifyResult = false; // default to access failure CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync( selectedCertificate, HashAlgorithmNames.Sha1, CryptographicPadding.RsaPkcs1V15); String buffer = "Data to sign"; IBuffer Data = CryptographicBuffer.ConvertStringToBinary(buffer, BinaryStringEncoding.Utf16BE); try { //sign the data by using the key IBuffer Signed = await CryptographicEngine.SignAsync(keyPair, Data); VerifyResult = CryptographicEngine.VerifySignature(keyPair, Data, Signed); } catch (Exception exp) { System.Diagnostics.Debug.WriteLine("Verification Failed. Exception Occurred : {0}", exp.Message); // default result is false so drop through to exit. } return(VerifyResult); }
private void GetTokenResponse(object Sender, IqResultEventArgs e) { object[] P = (object[])e.State; #if WINDOWS_UWP Certificate Certificate = (Certificate)P[0]; #else X509Certificate2 Certificate = (X509Certificate2)P[0]; #endif XmlElement E = e.FirstElement; if (e.Ok && E != null && E.LocalName == "getTokenChallenge" && E.NamespaceURI == NamespaceProvisioningToken) { int SeqNr = XML.Attribute(E, "seqnr", 0); string Challenge = E.InnerText; byte[] Bin = System.Convert.FromBase64String(Challenge); #if WINDOWS_UWP CryptographicKey Key = PersistedKeyProvider.OpenPublicKeyFromCertificate(Certificate, Certificate.SignatureHashAlgorithmName, CryptographicPadding.RsaPkcs1V15); IBuffer Buffer = CryptographicBuffer.CreateFromByteArray(Bin); Buffer = CryptographicEngine.Decrypt(Key, Buffer, null); CryptographicBuffer.CopyToByteArray(Buffer, out Bin); string Response = System.Convert.ToBase64String(Bin); #else Bin = Certificate.GetRSAPrivateKey().Decrypt(Bin, RSAEncryptionPadding.Pkcs1); string Response = System.Convert.ToBase64String(Bin); #endif this.client.SendIqGet(this.provisioningServerAddress, "<getTokenChallengeResponse xmlns='" + NamespaceProvisioningToken + "' seqnr='" + SeqNr.ToString() + "'>" + Response + "</getTokenChallengeResponse>", this.GetTokenChallengeResponse, P); } }
public bool TryCreateDeviceAuthChallengeResponseAsync(HttpResponseHeaders headers, Uri endpointUri, out string responseHeader) { responseHeader = string.Empty; Certificate certificate = null; string authHeaderTemplate = "PKeyAuth {0}, Context=\"{1}\", Version=\"{2}\""; if (!DeviceAuthHelper.IsDeviceAuthChallenge(headers)) { return(false); } if (!DeviceAuthHelper.CanOSPerformPKeyAuth()) { responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(headers); return(false); } IDictionary <string, string> challengeData = DeviceAuthHelper.ParseChallengeData(headers); if (!challengeData.ContainsKey("SubmitUrl")) { challengeData["SubmitUrl"] = endpointUri.AbsoluteUri; } try { certificate = Task.FromResult(FindCertificateAsync(challengeData)).Result.Result; } catch (MsalException ex) { if (ex.ErrorCode == MsalError.DeviceCertificateNotFound) { responseHeader = DeviceAuthHelper.GetBypassChallengeResponse(headers); return(true); } } DeviceAuthJWTResponse responseJWT = new DeviceAuthJWTResponse(challengeData["SubmitUrl"], challengeData["nonce"], Convert.ToBase64String(certificate.GetCertificateBlob().ToArray())); IBuffer input = CryptographicBuffer.ConvertStringToBinary(responseJWT.GetResponseToSign(), BinaryStringEncoding.Utf8); CryptographicKey keyPair = Task.FromResult(PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15)).Result.GetResults(); IBuffer signed = Task.FromResult(CryptographicEngine.SignAsync(keyPair, input)).Result.GetResults(); string signedJwt = string.Format(CultureInfo.InvariantCulture, "{0}.{1}", responseJWT.GetResponseToSign(), Base64UrlHelpers.Encode(signed.ToArray())); string authToken = string.Format(CultureInfo.InvariantCulture, " AuthToken=\"{0}\"", signedJwt); responseHeader = string.Format(CultureInfo.InvariantCulture, authHeaderTemplate, authToken, challengeData["Context"], challengeData["Version"]); return(true); }
public async Task <string> CreateDeviceAuthChallengeResponse(IDictionary <string, string> challengeData) { string authHeaderTemplate = "PKeyAuth {0}, Context=\"{1}\", Version=\"{2}\""; Certificate certificate = await FindCertificate(challengeData); DeviceAuthJWTResponse response = new DeviceAuthJWTResponse(challengeData["SubmitUrl"], challengeData["nonce"], Convert.ToBase64String(certificate.GetCertificateBlob().ToArray())); IBuffer input = CryptographicBuffer.ConvertStringToBinary(response.GetResponseToSign(), BinaryStringEncoding.Utf8); CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15); IBuffer signed = await CryptographicEngine.SignAsync(keyPair, input); string signedJwt = string.Format(CultureInfo.CurrentCulture, "{0}.{1}", response.GetResponseToSign(), Base64UrlEncoder.Encode(signed.ToArray())); string authToken = string.Format(CultureInfo.CurrentCulture, " AuthToken=\"{0}\"", signedJwt); return(string.Format(authHeaderTemplate, authToken, challengeData["Context"], challengeData["Version"])); }
/// <summary> /// Gets the private key for the certificate matching the specified selector. /// </summary> /// <remarks> /// Gets the private key for the first certificate that matches the specified selector. /// </remarks> /// <returns>The private key on success; otherwise <c>null</c>.</returns> /// <param name="selector">The search criteria for the private key.</param> protected virtual async Task <AsymmetricKeyParameter> GetPrivateKeyAsync(IX509Selector selector) { // first we need to find the certificate... var match = selector as X509CertStoreSelector; var query = new CertificateQuery(); if (match == null) { return(null); } if (match.Certificate != null) { query.Thumbprint = HexDecode(match.Certificate.GetFingerprint()); } if (match.Issuer != null) { query.IssuerName = match.Issuer.ToString(); } var certificates = await CertificateStores.FindAllAsync(query); var certificate = certificates.FirstOrDefault(); if (certificate == null) { return(null); } // now get the key // TODO: what hash algo/padding do we want? does it matter? var key = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(certificate, HashAlgorithmNames.Sha256, CryptographicPadding.RsaPkcs1V15); var buffer = key.Export(CryptographicPrivateKeyBlobType.Pkcs1RsaPrivateKey); return(LoadPrivateKey(buffer)); }
private void TokenChallengeHandler(object Sender, IqEventArgs e) { XmlElement E = e.Query; string Token = XML.Attribute(E, "token"); string Challenge = E.InnerText; CertificateUse Use; lock (this.certificates) { if (!this.certificates.TryGetValue(Token, out Use) || (DateTime.Now - Use.LastUse).TotalMinutes > 1) { throw new ForbiddenException("Token not recognized.", e.IQ); } } if (Use.LocalCertificate != null) { byte[] Bin = System.Convert.FromBase64String(Challenge); #if WINDOWS_UWP CryptographicKey Key = PersistedKeyProvider.OpenPublicKeyFromCertificate(Use.LocalCertificate, Use.LocalCertificate.SignatureHashAlgorithmName, CryptographicPadding.RsaPkcs1V15); IBuffer Buffer = CryptographicBuffer.CreateFromByteArray(Bin); Buffer = CryptographicEngine.Decrypt(Key, Buffer, null); CryptographicBuffer.CopyToByteArray(Buffer, out Bin); string Response = System.Convert.ToBase64String(Bin); #else Bin = Use.LocalCertificate.GetRSAPrivateKey().Decrypt(Bin, RSAEncryptionPadding.Pkcs1); string Response = System.Convert.ToBase64String(Bin); #endif e.IqResult("<tokenChallengeResponse xmlns='" + NamespaceProvisioningToken + "'>" + Response + "</tokenChallengeResponse>"); } else { this.client.SendIqGet(Use.RemoteCertificateJid, e.Query.OuterXml, this.ForwardedTokenChallengeResponse, e); } }
/// <summary> /// This is the click handler for the 'RunSample' button. It is responsible for executing the sample code. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void RunSample_Click(object sender, RoutedEventArgs e) { Certificate selectedCertificate = null; string verifyselection = VerifyCert.SelectionBoxItem.ToString(); //get the selected certificate if (CertificateList.SelectedIndex >= 0 && CertificateList.SelectedIndex < certList.Count) { selectedCertificate = certList[CertificateList.SelectedIndex]; } if (selectedCertificate == null) { ViewCertText.Text = "Please select a certificate first."; return; } // a certificate was selected, do the desired operation if (verifyselection.Equals("Verify Certificate")) { //Build the chain var chain = await selectedCertificate.BuildChainAsync(null, null); //Validate the chain var result = chain.Validate(); verifytext = "\n Verification Result :" + result.ToString(); } else if (verifyselection.Equals("Sign/Verify using certificate key")) { // get private key CryptographicKey keyPair = await PersistedKeyProvider.OpenKeyPairFromCertificateAsync(selectedCertificate, HashAlgorithmNames.Sha1, CryptographicPadding.RsaPkcs1V15); String cookie = "Some Data to sign"; IBuffer Data = CryptographicBuffer.ConvertStringToBinary(cookie, BinaryStringEncoding.Utf16BE); try { //sign the data by using the key IBuffer Signed = CryptographicEngine.Sign(keyPair, Data); bool bresult = CryptographicEngine.VerifySignature(keyPair, Data, Signed); if (bresult == true) { verifytext = "\n Verification Result : Successfully signed and verified signature"; } else { verifytext = "\n Verification Result : Verify Signature Failed"; } } catch (Exception exp) { verifytext = "\n Verification Failed. Exception Occurred :" + exp.Message; } } else if (verifyselection.Equals("Sign/Verify using CMS based format")) { IInputStream pdfInputstream; InMemoryRandomAccessStream originalData = new InMemoryRandomAccessStream(); //Populate the new memory stream pdfInputstream = originalData.GetInputStreamAt(0); CmsSignerInfo signer = new CmsSignerInfo(); signer.Certificate = selectedCertificate; signer.HashAlgorithmName = HashAlgorithmNames.Sha1; IList <CmsSignerInfo> signers = new List <CmsSignerInfo>(); signers.Add(signer); try { IBuffer signature = await CmsDetachedSignature.GenerateSignatureAsync(pdfInputstream, signers, null); CmsDetachedSignature cmsSignedData = new CmsDetachedSignature(signature); pdfInputstream = originalData.GetInputStreamAt(0); SignatureValidationResult validationResult = await cmsSignedData.VerifySignatureAsync(pdfInputstream); if (SignatureValidationResult.Success == validationResult) { verifytext = "\n Verification Result : Successfully signed and verified Signature"; } else { verifytext = "\n Verification Result : Verify Signature using CMS based format Failed"; } } catch (Exception exp) { verifytext = "\n Verification Failed. Exception Occurred :" + exp.Message; } } else if (verifyselection.Equals("Get certificate and show details")) { DisplayCertificate(selectedCertificate); } ViewCertText.Text += verifytext; verifytext = string.Empty; }