diff --git a/CyberSource/Client/BaseClient.cs b/CyberSource/Client/BaseClient.cs index 6f3b1aa..d1cbcdc 100644 --- a/CyberSource/Client/BaseClient.cs +++ b/CyberSource/Client/BaseClient.cs @@ -1,6 +1,7 @@ using CyberSource.Base; using System; using System.Net; +using System.Security.Cryptography.X509Certificates; using System.ServiceModel; using System.Xml.Serialization; using System.ServiceModel.Channels; @@ -359,5 +360,38 @@ protected static CustomBinding getWCFCustomBinding(Configuration config) currentBinding.Elements.Add(httpsTransport); return currentBinding; } + + /// + /// Creates a new instance of X509Certificate2 + /// + /// + /// Configuration object containing the key content or file path + /// + /// New instance of X509Certificate2 + protected static X509Certificate2 GetCertificate(Configuration config) + { + var flags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet; + return config.Key != null + ? new X509Certificate2(config.Key, config.EffectivePassword, flags) + : new X509Certificate2(config.EffectiveKeyFilePath, config.EffectivePassword, flags); + } + + /// + /// Creates a certificate collection with an imported certificate + /// + /// + /// Configuration object containing the key content or file path + /// + /// New instance of X509Certificate2Collection with an imported certificate + protected static X509Certificate2Collection GetCertificateCollection(Configuration config) + { + var collection = new X509Certificate2Collection(); + var flags = X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet; + if (config.Key != null) + collection.Import(config.Key, config.EffectivePassword, flags); + else + collection.Import(config.EffectiveKeyFilePath, config.EffectivePassword, flags); + return collection; + } } } diff --git a/CyberSource/Client/Configuration.cs b/CyberSource/Client/Configuration.cs index 500a148..b5604e2 100644 --- a/CyberSource/Client/Configuration.cs +++ b/CyberSource/Client/Configuration.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace CyberSource.Clients { @@ -62,6 +63,7 @@ public class Configuration private string logDirectory = null; private string serverURL = null; private string keyFilename = null; + private byte[] key = null; private string password = null; private string logFilename = null; private int logMaximumSize = -1; @@ -161,6 +163,15 @@ public string ServerURL set { serverURL = value; } } + /// + /// This is optional. When set, it reads key from memory rather than from file system + /// + public byte[] Key + { + get { return key; } + set { key = value; } + } + /// /// Corresponds to [cybs.][merchantID].keyFilename. /// @@ -380,6 +391,18 @@ internal string EffectiveKeyFilename } } + /// + /// Return the key file path that will take effect given + /// the current state of this Configuration object. + /// + internal string EffectiveKeyFilePath + { + get + { + return Path.Combine(KeysDirectory, EffectiveKeyFilename); + } + } + /// /// Returns the password that will take effect given /// the current state of this Configuration object. diff --git a/CyberSource/Client/NVPClient.cs b/CyberSource/Client/NVPClient.cs index 3c9cbd7..92d89a4 100644 --- a/CyberSource/Client/NVPClient.cs +++ b/CyberSource/Client/NVPClient.cs @@ -80,13 +80,12 @@ public static Hashtable RunTransaction( string keyFilePath = Path.Combine(config.KeysDirectory, config.EffectiveKeyFilename); - proc.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + proc.ClientCredentials.ClientCertificate.Certificate = GetCertificate(config); proc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None; // Changes for SHA2 certificates support - X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = GetCertificateCollection(config); foreach (X509Certificate2 cert1 in collection) { diff --git a/CyberSource/Client/SoapClient.cs b/CyberSource/Client/SoapClient.cs index 139295f..8717e99 100644 --- a/CyberSource/Client/SoapClient.cs +++ b/CyberSource/Client/SoapClient.cs @@ -79,15 +79,13 @@ public static ReplyMessage RunTransaction( currentBinding.SendTimeout = timeOut; //add certificate credentials - string keyFilePath = Path.Combine(config.KeysDirectory,config.EffectiveKeyFilename); - proc.ClientCredentials.ClientCertificate.Certificate = new X509Certificate2(keyFilePath,config.EffectivePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + proc.ClientCredentials.ClientCertificate.Certificate = GetCertificate(config); + + proc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None; + + // Changes for SHA2 certificates support + X509Certificate2Collection collection = GetCertificateCollection(config); - proc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None; - - // Changes for SHA2 certificates support - X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); - foreach (X509Certificate2 cert1 in collection) { if (cert1.Subject.Contains(config.MerchantID)) diff --git a/CyberSource/Client/XmlClient.cs b/CyberSource/Client/XmlClient.cs index 51a9bc8..0f32eb4 100644 --- a/CyberSource/Client/XmlClient.cs +++ b/CyberSource/Client/XmlClient.cs @@ -84,13 +84,11 @@ public static XmlDocument RunTransaction( XmlDocument doc = SoapWrap(request, nspace); //Get the X509 cert and sign the SOAP Body - string keyFilePath = Path.Combine(config.KeysDirectory, config.EffectiveKeyFilename); X509Certificate2 cert = null; X509Certificate2 cybsCert = null; - X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = GetCertificateCollection(config); foreach (X509Certificate2 cert1 in collection) {