public static void VerifyApplicationCertIntegrity( X509Certificate2 newCert, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, X509Certificate2Collection issuerCertificates) { Assert.NotNull(newCert); if (privateKey != null) { X509Certificate2 newPrivateKeyCert = null; if (privateKeyFormat == "PFX") { newPrivateKeyCert = CertificateFactory.CreateCertificateFromPKCS12(privateKey, privateKeyPassword); } else if (privateKeyFormat == "PEM") { newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword); } else { Assert.True(false, "Invalid private key format"); } Assert.NotNull(newPrivateKeyCert); // verify the public cert matches the private key Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); } CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in issuerCertificates) { issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateTrustList trustedStore = new CertificateTrustList(); trustedStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <Opc.Ua.ServiceResultException>(() => { certValidator.Validate(newCert); }); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
/// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyCertificate(X509Certificate2 certificate) { try { if (m_certificateValidator != null) { m_certificateValidator.Validate(certificate); } else { CertificateValidator.Validate(certificate); } } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; if (e is ServiceResultException se && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; }
/// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyCertificate(X509Certificate2 certificate) { try { CertificateValidator.Validate(certificate); // determine if self-signed. bool isSelfSigned = Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer); // do not allow self signed application certs as user token if (isSelfSigned && Utils.HasApplicationURN(certificate)) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed); } } catch (Exception) { // construct translation object with default text. TranslationInfo info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( StatusCodes.BadIdentityTokenRejected, "InvalidCertificate", "http://opcfoundation.org/UA/Sample/", new LocalizedText(info))); } }
public void CertificateValidation_ArgumentNullException() { var validator = new CertificateValidator(); var error = validator.Validate(null, X509KeyUsageFlags.NonRepudiation); Assert.AreEqual(CertificateErrors.Missing, error); }
public void RemoteCertificateValidationRulesTest() { //ARRANGE var configurationProvider = new CertificateValidationConfigurationProvider(); var validator = new CertificateValidator(configurationProvider); var certificateStore = new X509Store("TestCertStore", StoreLocation.LocalMachine); var validationResult = false; //ACT try { certificateStore.Open(OpenFlags.ReadOnly); var certificate = certificateStore.Certificates.Find(X509FindType.FindBySubjectName, "ApiraTestCertificate", false)[0]; var x509Chain = new X509Chain(true); x509Chain.Build(certificate); validationResult = validator.Validate(this, certificate, x509Chain, SslPolicyErrors.None); } finally { certificateStore.Close(); certificateStore.Dispose(); } //ASSERT Assert.True(validationResult); }
/// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyUserTokenCertificate(X509Certificate2 certificate) { try { CertificateValidator.Validate(certificate); // determine if self-signed. bool isSelfSigned = Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer); // do not allow self signed application certs as user token if (isSelfSigned && Utils.HasApplicationURN(certificate)) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed); } } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; if (e is ServiceResultException se && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; }
public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, byte[][] issuerCertificates) { X509Certificate2 newCert = new X509Certificate2(certificate); Assert.IsNotNull(newCert); X509Certificate2 newPrivateKeyCert = null; if (privateKeyFormat == "PFX") { newPrivateKeyCert = X509Utils.CreateCertificateFromPKCS12(privateKey, privateKeyPassword); } else if (privateKeyFormat == "PEM") { newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword); } else { Assert.Fail("Invalid private key format"); } Assert.IsNotNull(newPrivateKeyCert); // verify the public cert matches the private key Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuer in issuerCertificates) { var issuerCert = new X509Certificate2(issuer); Assert.IsNotNull(issuerCert); issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateTrustList trustedStore = new CertificateTrustList(); trustedStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(trustedStore, issuerStore, null); Assert.That(() => { certValidator.Validate(newCert); }, Throws.Exception); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
public void CertificateValidation_Usage() { var validator = new CertificateValidator(); var error = validator.Validate(TestCertificates.CounterpartyPublicSignature, X509KeyUsageFlags.DataEncipherment); Assert.AreEqual(CertificateErrors.Usage, error); }
public void CertificateValidation_EndDate() { var validator = new CertificateValidator(); var error = validator.Validate(TestCertificates.CounterpartyPublicSignatureInvalidEnd, X509KeyUsageFlags.NonRepudiation); Assert.AreEqual(CertificateErrors.EndDate, error); }
public void RemoteCertificateValidationCallbackTest() { //ARRANGE var configurationProvider = new CertificateValidationConfigurationProvider(); var validator = new CertificateValidator(configurationProvider); //ACT //ASSERT Assert.Throws <NotImplementedException>(() => validator.Validate(null, null, null, System.Net.Security.SslPolicyErrors.None)); }
public void MetadataSerialisationCertificateTest() { //ARRANGE var configurationProvider = new CertificateValidationConfigurationProvider(); var validator = new CertificateValidator(configurationProvider); //ACT //ASSERT Assert.Throws <NotImplementedException>(() => validator.Validate((X509Certificate2)null)); }
public static void VerifyApplicationCertIntegrity( X509Certificate2 newCert, Key privateKey, X509Certificate2Collection issuerCertificates) { Assert.NotNull(newCert); Assert.True(privateKey.HasPrivateKey()); if (privateKey != null) { using (var newPrivateKeyCert = new X509Certificate2(newCert.RawData) { PrivateKey = privateKey.ToRSA() }) { Assert.True(newPrivateKeyCert.HasPrivateKey); Assert.NotNull(newPrivateKeyCert); Assert.True(newPrivateKeyCert.HasPrivateKey); // verify the public cert matches the private key Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); } } var issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in issuerCertificates) { issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain var certValidator = new CertificateValidator(); var issuerStore = new CertificateTrustList(); var trustedStore = new CertificateTrustList { TrustedCertificates = issuerCertIdCollection }; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <ServiceResultException>(() => certValidator.Validate(newCert)); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
private static bool ValidateCertificate(X509Certificate2 certificate) { try { smpCertificateValidator.Validate(certificate); // Valid if no exception was thrown: return(true); } catch (SecurityTokenValidationException) { return(false); } }
/// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyUserTokenCertificate(X509Certificate2 certificate) { try { CertificateValidator.Validate(certificate); // determine if self-signed. bool isSelfSigned = Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer); // do not allow self signed application certs as user token if (isSelfSigned && Utils.HasApplicationURN(certificate)) { throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed); } } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; ServiceResultException se = e as ServiceResultException; if (se != null && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; } else { // construct translation object with default text. info = new TranslationInfo( "UntrustedCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); } // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( result, info.Key, LoadServerProperties().ProductUri, new LocalizedText(info))); } }
public void validate_certificate_path() { var rootKey = new Key(512); var interKey = new Key(512); var finalKey = new Key(512); Certificate rootCert = GetCert("cn=root.test", rootKey, "cn=root.test", rootKey); Certificate interCert = GetCert("cn=inter.test", interKey, "cn=root.test", rootKey); Certificate finalCert = GetCert("cn=final.test", finalKey, "cn=inter.test", interKey); var certificates = new List<Certificate> {rootCert, interCert}; var certificateValidator = new CertificateValidator(certificates); var result = certificateValidator.Validate(finalCert); Console.WriteLine(result); }
/// <summary> /// Verifies that a certificate user token is trusted. /// </summary> private void VerifyUserTokenCertificate(X509Certificate2 certificate) { try { if (m_certificateValidator != null) { m_certificateValidator.Validate(certificate); } else { CertificateValidator.Validate(certificate); } } catch (Exception e) { TranslationInfo info; StatusCode result = StatusCodes.BadIdentityTokenRejected; ServiceResultException se = e as ServiceResultException; if (se != null && se.StatusCode == StatusCodes.BadCertificateUseNotAllowed) { info = new TranslationInfo( "InvalidCertificate", "en-US", "'{0}' is an invalid user certificate.", certificate.Subject); result = StatusCodes.BadIdentityTokenInvalid; } else { // construct translation object with default text. info = new TranslationInfo( "UntrustedCertificate", "en-US", "'{0}' is not a trusted user certificate.", certificate.Subject); } // create an exception with a vendor defined sub-code. throw new ServiceResultException(new ServiceResult( result, info.Key, LoadServerProperties().ProductUri, new LocalizedText(info))); } }
public void MetadataSerialisationCertificateTest_failed() { //ARRANGE var store = new X509Store("TestCertStore"); try { store.Open(OpenFlags.ReadOnly); var certificate = store.Certificates.Find(X509FindType.FindBySubjectName, "ApiraTestCertificate", false)[0]; var configuration = new CertificateValidationConfiguration { UsePinningValidation = false, X509CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.Custom }; var rule1 = typeof(CertificateValidationRuleMock1).AssemblyQualifiedName; var rule2 = typeof(CertificateValidationRuleFailedMock).AssemblyQualifiedName; var ruleDescriptor = new ValidationRuleDescriptor(rule1); var ruleDescriptor2 = new ValidationRuleDescriptor(rule2); configuration.ValidationRules.Add(ruleDescriptor); configuration.ValidationRules.Add(ruleDescriptor2); configuration.ValidationRules.Add(new ValidationRuleDescriptor(rule1)); var configurationProvider = new CertificateValidationConfigurationProvider(() => configuration); var validator = new CertificateValidator(configurationProvider); //ACT //ASSERT Assert.Throws <InvalidOperationException>(() => validator.Validate(certificate)); } finally { store.Close(); store.Dispose(); } }
public void MetadataSerialisationCertificateTest_success() { //ARRANGE var logger = new LogProviderMock(); var store = new X509Store("TestCertStore"); try { store.Open(OpenFlags.ReadOnly); var certificate = store.Certificates.Find(X509FindType.FindBySubjectName, "www.eca-international.com", false)[0]; var configuration = new CertificateValidationConfiguration { X509CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.Custom }; var rule1 = typeof(CertificateValidationRuleMock1).AssemblyQualifiedName; var rule2 = typeof(CertificateValidationRuleMock).AssemblyQualifiedName; var ruleDescriptor = new ValidationRuleDescriptor(rule1); var ruleDescriptor2 = new ValidationRuleDescriptor(rule2); configuration.ValidationRules.Add(ruleDescriptor); configuration.ValidationRules.Add(ruleDescriptor2); configuration.ValidationRules.Add(new ValidationRuleDescriptor(rule1)); var configurationProvider = new CertificateValidationConfigurationProvider(() => configuration); var validator = new CertificateValidator(configurationProvider, logger); //ACT validator.Validate(certificate); //ASSERT } finally { store.Close(); store.Dispose(); } }
/// <summary> /// Processes an OpenSecureChannel request message. /// </summary> protected ArraySegment <byte> ReadAsymmetricMessage( ArraySegment <byte> buffer, X509Certificate2 receiverCertificate, out uint channelId, out X509Certificate2 senderCertificate, out uint requestId, out uint sequenceNumber) { BinaryDecoder decoder = new BinaryDecoder(buffer.Array, buffer.Offset, buffer.Count, Quotas.MessageContext); string securityPolicyUri = null; X509Certificate2Collection senderCertificateChain; // parse the security header. ReadAsymmetricMessageHeader( decoder, receiverCertificate, out channelId, out senderCertificateChain, out securityPolicyUri); if (senderCertificateChain != null && senderCertificateChain.Count > 0) { senderCertificate = senderCertificateChain[0]; } else { senderCertificate = null; } // validate the sender certificate. if (senderCertificate != null && Quotas.CertificateValidator != null && securityPolicyUri != SecurityPolicies.None) { CertificateValidator certificateValidator = Quotas.CertificateValidator as CertificateValidator; if (certificateValidator != null) { certificateValidator.Validate(senderCertificateChain); } else { Quotas.CertificateValidator.Validate(senderCertificate); } } // check if this is the first open secure channel request. if (!m_uninitialized) { if (securityPolicyUri != m_securityPolicyUri) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "Cannot change the security policy after creating the channnel."); } } else { // find a matching endpoint description. if (m_endpoints != null) { foreach (EndpointDescription endpoint in m_endpoints) { // There may be multiple endpoints with the same securityPolicyUri. // Just choose the first one that matches. This choice will be re-examined // When the OpenSecureChannel request body is processed. if (endpoint.SecurityPolicyUri == securityPolicyUri || (securityPolicyUri == SecurityPolicies.None && endpoint.SecurityMode == MessageSecurityMode.None)) { m_securityMode = endpoint.SecurityMode; m_securityPolicyUri = securityPolicyUri; m_discoveryOnly = false; m_uninitialized = false; m_selectedEndpoint = endpoint; // recalculate the key sizes. CalculateSymmetricKeySizes(); break; } } } // allow a discovery only channel with no security if policy not suppported if (m_uninitialized) { if (securityPolicyUri != SecurityPolicies.None) { throw ServiceResultException.Create(StatusCodes.BadSecurityPolicyRejected, "The security policy is not supported."); } m_securityMode = MessageSecurityMode.None; m_securityPolicyUri = SecurityPolicies.None; m_discoveryOnly = true; m_uninitialized = false; m_selectedEndpoint = null; } } int headerSize = decoder.Position; // decrypt the body. ArraySegment <byte> plainText = Decrypt( new ArraySegment <byte>(buffer.Array, buffer.Offset + headerSize, buffer.Count - headerSize), new ArraySegment <byte>(buffer.Array, buffer.Offset, headerSize), receiverCertificate); // extract signature. int signatureSize = GetAsymmetricSignatureSize(senderCertificate); byte[] signature = new byte[signatureSize]; for (int ii = 0; ii < signatureSize; ii++) { signature[ii] = plainText.Array[plainText.Offset + plainText.Count - signatureSize + ii]; } // verify the signature. ArraySegment <byte> dataToVerify = new ArraySegment <byte>(plainText.Array, plainText.Offset, plainText.Count - signatureSize); if (!Verify(dataToVerify, signature, senderCertificate)) { Utils.Trace("Could not verify signature on message."); throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the signature on the message."); } // verify padding. int paddingCount = 0; if (SecurityMode != MessageSecurityMode.None) { int paddingEnd = -1; if (CertificateFactory.GetRSAPublicKeySize(receiverCertificate) > TcpMessageLimits.KeySizeExtraPadding) { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd - 1] + plainText.Array[paddingEnd] * 256; //parse until paddingStart-1; the last one is actually the extrapaddingsize for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd - 1]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } else { paddingEnd = plainText.Offset + plainText.Count - signatureSize - 1; paddingCount = plainText.Array[paddingEnd]; for (int ii = paddingEnd - paddingCount; ii < paddingEnd; ii++) { if (plainText.Array[ii] != plainText.Array[paddingEnd]) { throw ServiceResultException.Create(StatusCodes.BadSecurityChecksFailed, "Could not verify the padding in the message."); } } } paddingCount++; } // decode message. decoder = new BinaryDecoder( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize, Quotas.MessageContext); sequenceNumber = decoder.ReadUInt32(null); requestId = decoder.ReadUInt32(null); headerSize += decoder.Position; decoder.Close(); Utils.Trace("Security Policy: {0}", SecurityPolicyUri); Utils.Trace("Sender Certificate: {0}", (senderCertificate != null) ? senderCertificate.Subject : "(none)"); // return the body. return(new ArraySegment <byte>( plainText.Array, plainText.Offset + headerSize, plainText.Count - headerSize - signatureSize - paddingCount)); }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // validate new subject matches the previous subject if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = X509Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; if (updateCertificate != null) { try { using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore()) { Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate); appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey); var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait(); // keep only track of cert without private key var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData); updateCertificate.CertificateWithPrivateKey.Dispose(); updateCertificate.CertificateWithPrivateKey = certOnly; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer); issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } } catch (Exception ex) { Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex)); throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex); } } return(ServiceResult.Good); }
public (SignalProtocolAddress, byte[]) Decrypt(CertificateValidator validator, byte[] ciphertext, long timestamp) { UnidentifiedSenderMessageContent content; try { IdentityKeyPair ourIdentity = SignalProtocolStore.GetIdentityKeyPair(); UnidentifiedSenderMessage wrapper = new UnidentifiedSenderMessage(ciphertext); byte[] ephemeralSalt = ByteUtil.combine(Encoding.ASCII.GetBytes("UnidentifiedDelivery"), ourIdentity.getPublicKey().getPublicKey().serialize(), wrapper.Ephemeral.serialize()); EphemeralKeys ephemeralKeys = CalculateEphemeralKeys(wrapper.Ephemeral, ourIdentity.getPrivateKey(), ephemeralSalt); byte[] staticKeyBytes = Decrypt(ephemeralKeys.CipherKey, ephemeralKeys.MacKey, wrapper.EncryptedStatic); ECPublicKey staticKey = Curve.decodePoint(staticKeyBytes, 0); byte[] staticSalt = ByteUtil.combine(ephemeralKeys.ChainKey, wrapper.EncryptedStatic); StaticKeys staticKeys = CalculateStaticKeys(staticKey, ourIdentity.getPrivateKey(), staticSalt); byte[] messageBytes = Decrypt(staticKeys.CipherKey, staticKeys.MacKey, wrapper.EncryptedMessage); content = new UnidentifiedSenderMessageContent(messageBytes); validator.Validate(content.SenderCertificate, timestamp); if (!Enumerable.SequenceEqual(content.SenderCertificate.Key.serialize(), staticKeyBytes)) { throw new libsignal.InvalidKeyException("Sender's certificate key does not match key used in message"); } if (content.SenderCertificate.Sender == LocalAddress.Name && content.SenderCertificate.SenderDeviceId == LocalAddress.DeviceId) { throw new SelfSendException(); } } catch (libsignal.InvalidKeyException e) { throw new InvalidMetadataMessageException(e); } catch (InvalidCertificateException e) { throw new InvalidMetadataMessageException(e); } catch (InvalidMacException e) { throw new InvalidMetadataMessageException(e); } try { return(new SignalProtocolAddress(content.SenderCertificate.Sender, (uint)content.SenderCertificate.SenderDeviceId), Decrypt(content)); } catch (InvalidMessageException e) { throw new ProtocolInvalidMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (libsignal.InvalidKeyException e) { throw new ProtocolInvalidKeyException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (NoSessionException e) { throw new ProtocolNoSessionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (LegacyMessageException e) { throw new ProtocolLegacyMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (InvalidVersionException e) { throw new ProtocolInvalidVersionException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (DuplicateMessageException e) { throw new ProtocolDuplicateMessageException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (InvalidKeyIdException e) { throw new ProtocolInvalidKeyIdException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } catch (UntrustedIdentityException e) { throw new ProtocolUntrustedIdentityException(e, content.SenderCertificate.Sender, content.SenderCertificate.SenderDeviceId); } }
public static void VerifySignedApplicationCert(ApplicationTestData testApp, X509Certificate2 signedCert, X509Certificate2Collection issuerCerts) { var issuerCert = issuerCerts[0]; var signedCertO = signedCert.ToCertificate(); Assert.NotNull(signedCertO); Assert.False(signedCert.HasPrivateKey); Assert.True(Utils.CompareDistinguishedName(testApp.Subject, signedCert.Subject)); Assert.False(Utils.CompareDistinguishedName(signedCert.Issuer, signedCert.Subject)); Assert.True(Utils.CompareDistinguishedName(signedCert.Issuer, issuerCert.Subject)); // test basic constraints var constraints = signedCertO.GetBasicConstraintsExtension(); Assert.NotNull(constraints); Assert.True(constraints.Critical); Assert.False(constraints.CertificateAuthority); Assert.False(constraints.HasPathLengthConstraint); // key usage var keyUsage = signedCertO.GetKeyUsageExtension(); Assert.NotNull(keyUsage); Assert.True(keyUsage.Critical); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.CrlSign) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DataEncipherment) == X509KeyUsageFlags.DataEncipherment); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DecipherOnly) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.DigitalSignature); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.EncipherOnly) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyAgreement) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyCertSign) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyEncipherment) == X509KeyUsageFlags.KeyEncipherment); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.NonRepudiation); // enhanced key usage var enhancedKeyUsage = signedCertO.GetEnhancedKeyUsageExtension(); Assert.NotNull(enhancedKeyUsage); Assert.True(enhancedKeyUsage.Critical); // test for authority key var authority = signedCertO.GetAuthorityKeyIdentifierExtension(); Assert.NotNull(authority); Assert.NotNull(authority.SerialNumber); Assert.NotNull(authority.KeyId); Assert.NotNull(authority.AuthorityNames); // verify authority key in signed cert var subjectKeyId = signedCertO.GetSubjectKeyIdentifierExtension(); Assert.Equal(subjectKeyId.SubjectKeyIdentifier, authority.KeyId); Assert.Equal(issuerCert.SerialNumber, authority.SerialNumber.ToString()); var subjectAlternateName = signedCertO.GetSubjectAltNameExtension(); Assert.NotNull(subjectAlternateName); Assert.False(subjectAlternateName.Critical); var domainNames = Utils.GetDomainsFromCertficate(signedCert); foreach (var domainName in testApp.DomainNames) { Assert.Contains(domainName, domainNames, StringComparer.OrdinalIgnoreCase); } Assert.True(subjectAlternateName.Uris.Count == 1); var applicationUri = Utils.GetApplicationUriFromCertificate(signedCert); Assert.True(testApp.ApplicationRecord.ApplicationUri == applicationUri); var issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var cert in issuerCerts) { issuerCertIdCollection.Add(new CertificateIdentifier(cert)); } // verify cert with issuer chain var certValidator = new CertificateValidator(); var issuerStore = new CertificateTrustList(); var trustedStore = new CertificateTrustList { TrustedCertificates = issuerCertIdCollection }; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <ServiceResultException>(() => certValidator.Validate(signedCert)); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(signedCert); }
/// <summary> /// Validates a certificate and adds it to the trust list. /// </summary> private void ValidateAndImport(CertificateStoreIdentifier store, X509Certificate2 certificate) { if (store == null || certificate == null) { return; } // validate the certificate using the trust lists for the certificate tool. try { CertificateValidator validator = new CertificateValidator(); validator.Update(m_configuration); validator.Validate(certificate); } catch (ServiceResultException exception) { if (!HandleValidationError(certificate, exception)) { return; } } // confirm import. StringBuilder buffer = new StringBuilder(); buffer.Append("You are adding this certificate to a trust list that may be shared with other applications."); buffer.Append("\r\n"); buffer.Append("\r\n"); buffer.Append("Would you still like to accept the certificate?\r\n"); buffer.Append("\r\n"); buffer.Append("Target Trust List = "); buffer.Append(store.ToString()); buffer.Append("\r\n"); buffer.Append("Certificate to Add = "); buffer.Append(certificate.Subject); DialogResult result = new YesNoDlg().ShowDialog(buffer.ToString(), "Import Certificate to Trust List"); if (result != DialogResult.Yes) { return; } // update store. ICertificateStore physicalStore = store.OpenStore(); if (physicalStore.FindByThumbprint(certificate.Thumbprint) == null) { physicalStore.Add(new X509Certificate2(certificate.RawData)); } }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // load existing application cert and private key if (!Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { string password = String.Empty; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKey(password).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = CertificateFactory.CreateCertificateFromPKCS12(privateKey, password); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, password); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; return(ServiceResult.Good); }