From 5a01e1a22ecc3553cd6247d5a4b9ca0e5bc5cff5 Mon Sep 17 00:00:00 2001 From: gnongsie Date: Fri, 28 Jun 2024 13:42:06 +0530 Subject: [PATCH 1/5] Changed string to SecureString --- CyberSource/Client/BaseClient.cs | 34 ++++++++++++++++++++++++----- CyberSource/Client/Configuration.cs | 25 +++++++++++++++++---- CyberSource/Client/NVPClient.cs | 16 +++++++++----- CyberSource/Client/SoapClient.cs | 10 ++++++--- CyberSource/Client/XmlClient.cs | 9 ++++++-- 5 files changed, 74 insertions(+), 20 deletions(-) diff --git a/CyberSource/Client/BaseClient.cs b/CyberSource/Client/BaseClient.cs index 0629f26..daed9b4 100644 --- a/CyberSource/Client/BaseClient.cs +++ b/CyberSource/Client/BaseClient.cs @@ -7,7 +7,8 @@ using System.ServiceModel.Channels; using System.ServiceModel.Security.Tokens; using System.Security.Cryptography.X509Certificates; -using System.Collections.Concurrent; +using System.Collections.Concurrent; +using System.Security; namespace CyberSource.Clients { @@ -70,8 +71,14 @@ string proxyUser = AppSettings.GetSetting(null, PROXY_USER); if (proxyUser != null) { - string proxyPassword - = AppSettings.GetSetting(null, PROXY_PASSWORD); + SecureString proxyPassword = new SecureString(); + + foreach (char c in AppSettings.GetSetting(null, PROXY_PASSWORD)) + { + proxyPassword.AppendChar(c); + } + + proxyPassword.MakeReadOnly(); NetworkCredential credential = new NetworkCredential(proxyUser, proxyPassword); @@ -79,6 +86,7 @@ NetworkCredential credential CredentialCache cache = new CredentialCache(); cache.Add(new Uri(proxyURL), BASIC_AUTH, credential); mProxy.Credentials = cache; + proxyPassword.Dispose(); } } } @@ -201,8 +209,8 @@ int boolVal merchantID, Configuration.KEY_ALIAS); config.Password - = AppSettings.GetSetting( - merchantID, Configuration.PASSWORD); + = convertToSecureString(AppSettings.GetSetting( + merchantID, Configuration.PASSWORD)); config.LogFilename = AppSettings.GetSetting( @@ -422,6 +430,22 @@ public static bool IsMerchantCertExpired(Logger logger, string merchantId, DateT } return false; + } + + private static SecureString convertToSecureString(string originalString) + { + if (originalString == null) + { + return null; + } + + var secureString = new SecureString(); + + foreach (char c in originalString) + secureString.AppendChar(c); + + secureString.MakeReadOnly(); + return secureString; } } } diff --git a/CyberSource/Client/Configuration.cs b/CyberSource/Client/Configuration.cs index e9f32ec..ffa38e4 100644 --- a/CyberSource/Client/Configuration.cs +++ b/CyberSource/Client/Configuration.cs @@ -1,4 +1,5 @@ using System; +using System.Security; namespace CyberSource.Clients { @@ -65,7 +66,7 @@ public class Configuration private string serverURL = null; private string keyFilename = null; private string keyAlias = null; - private string password = null; + private SecureString password = null; private string logFilename = null; private int logMaximumSize = -1; private int timeout = -1; @@ -195,7 +196,7 @@ public string KeyAlias /// This is optional. When not set, the value of MerchantID is /// used. /// - public string Password + public SecureString Password { get { return password; } set { password = value; } @@ -409,14 +410,30 @@ internal string EffectiveKeyFilename /// Returns the password that will take effect given /// the current state of this Configuration object. /// - internal string EffectivePassword + internal SecureString EffectivePassword { get { - return( password != null ? password : merchantID); + return( password != null ? password : convertToSecureString(merchantID)); } } + private SecureString convertToSecureString(string originalString) + { + if (originalString == null) + { + return null; + } + + var secureString = new SecureString(); + + foreach (char c in originalString) + secureString.AppendChar(c); + + secureString.MakeReadOnly(); + return secureString; + } + /// /// Returns the merchantID. Throws an exception when it is null. /// diff --git a/CyberSource/Client/NVPClient.cs b/CyberSource/Client/NVPClient.cs index adb6da4..d5f8747 100644 --- a/CyberSource/Client/NVPClient.cs +++ b/CyberSource/Client/NVPClient.cs @@ -86,9 +86,12 @@ public static Hashtable RunTransaction( if (logger != null) { logger.LogInfo("Loading certificate for " + config.KeyAlias); - } - X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + } + + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Add(userCertificate); X509Certificate2 newMerchantCert = null; X509Certificate2 newCybsCert = null; @@ -121,9 +124,10 @@ public static Hashtable RunTransaction( } else { - // Changes for SHA2 certificates support - X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + + X509Certificate2Collection collection = new X509Certificate2Collection(); + collection.Add(userCertificate); foreach (X509Certificate2 cert1 in collection) { diff --git a/CyberSource/Client/SoapClient.cs b/CyberSource/Client/SoapClient.cs index 6dd8dc6..5eac54e 100644 --- a/CyberSource/Client/SoapClient.cs +++ b/CyberSource/Client/SoapClient.cs @@ -81,6 +81,7 @@ public static ReplyMessage RunTransaction( X509Certificate2 merchantCert = null; X509Certificate2 cybsCert = null; DateTime dateFile = File.GetLastWriteTime(keyFilePath); + if (config.CertificateCacheEnabled) { if (!merchantIdentities.ContainsKey(config.KeyAlias) || IsMerchantCertExpired(logger, config.KeyAlias, dateFile, merchantIdentities)) @@ -90,8 +91,10 @@ public static ReplyMessage RunTransaction( logger.LogInfo("Loading certificate for " + config.KeyAlias); } + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + collection.Add(userCertificate); X509Certificate2 newMerchantCert = null; X509Certificate2 newCybsCert = null; @@ -124,9 +127,10 @@ public static ReplyMessage RunTransaction( } else { - // Changes for SHA2 certificates support + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + collection.Add(userCertificate); foreach (X509Certificate2 cert1 in collection) { diff --git a/CyberSource/Client/XmlClient.cs b/CyberSource/Client/XmlClient.cs index 9964b67..2d04107 100644 --- a/CyberSource/Client/XmlClient.cs +++ b/CyberSource/Client/XmlClient.cs @@ -106,8 +106,10 @@ public static XmlDocument RunTransaction( logger.LogInfo("Loading certificate for "+ config.KeyAlias); } + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + collection.Add(userCertificate); X509Certificate2 newMerchantCert = null; X509Certificate2 newCybsCert = null; @@ -140,8 +142,11 @@ public static XmlDocument RunTransaction( } else { + X509Certificate2 userCertificate = new X509Certificate2(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + X509Certificate2Collection collection = new X509Certificate2Collection(); - collection.Import(keyFilePath, config.EffectivePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); + collection.Add(userCertificate); + foreach (X509Certificate2 cert1 in collection) { if (cert1.Subject.Contains(config.KeyAlias)) From 971442ce1aa8c8fb33792d6ed480ae2a63618b3d Mon Sep 17 00:00:00 2001 From: gnongsie Date: Mon, 1 Jul 2024 13:15:54 +0530 Subject: [PATCH 2/5] Preparation for next upgrade --- CyberSource.nuspec | 2 +- CyberSource/Base/Properties/AssemblyInfo.cs | 4 ++-- CyberSource/Client/Properties/AssemblyInfo.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CyberSource.nuspec b/CyberSource.nuspec index b08c1f5..2a11eba 100644 --- a/CyberSource.nuspec +++ b/CyberSource.nuspec @@ -2,7 +2,7 @@ CyberSource - 1.4.6 + 1.4.7 CyberSource Corporation CyberSource Corporation CyberSource Corporation diff --git a/CyberSource/Base/Properties/AssemblyInfo.cs b/CyberSource/Base/Properties/AssemblyInfo.cs index 8c18b19..192fc95 100644 --- a/CyberSource/Base/Properties/AssemblyInfo.cs +++ b/CyberSource/Base/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.4.6")] -[assembly: AssemblyFileVersion("1.4.6")] +[assembly: AssemblyVersion("1.4.7")] +[assembly: AssemblyFileVersion("1.4.7")] diff --git a/CyberSource/Client/Properties/AssemblyInfo.cs b/CyberSource/Client/Properties/AssemblyInfo.cs index 5bfad26..022c3d7 100644 --- a/CyberSource/Client/Properties/AssemblyInfo.cs +++ b/CyberSource/Client/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.4.6")] -[assembly: AssemblyFileVersion("1.4.6")] +[assembly: AssemblyVersion("1.4.7")] +[assembly: AssemblyFileVersion("1.4.7")] From d699b237ec153c8624a1dde61ec879206f35bebd Mon Sep 17 00:00:00 2001 From: Gabriel Broadwin Nongsiej Date: Thu, 18 Jul 2024 14:31:55 +0530 Subject: [PATCH 3/5] Changes to test SecureString --- .../SoapServiceReference/Reference.cs | 18 ++++++++--- CyberSourceSamples/src/soap/SoapSample.cs | 32 ++++++++++++++----- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CyberSource/Client/Service References/SoapServiceReference/Reference.cs b/CyberSource/Client/Service References/SoapServiceReference/Reference.cs index d5571c0..69958f1 100644 --- a/CyberSource/Client/Service References/SoapServiceReference/Reference.cs +++ b/CyberSource/Client/Service References/SoapServiceReference/Reference.cs @@ -31953,7 +31953,7 @@ public partial class BillTo : object, System.ComponentModel.INotifyPropertyChang private string phoneNumberField; - private string emailField; + private System.Security.SecureString emailField; private string ipAddressField; @@ -32281,12 +32281,13 @@ public string phoneNumber { /// [System.Xml.Serialization.XmlElementAttribute(Order=20)] - public string email { + public System.Security.SecureString email { get { return this.emailField; } set { this.emailField = value; + this.emailField.MakeReadOnly(); this.RaisePropertyChanged("email"); } } @@ -47985,7 +47986,7 @@ public partial class PayerAuthEnrollService : object, System.ComponentModel.INot private string loginIDField; - private string passwordField; + private System.Security.SecureString passwordField; private string merchantIDField; @@ -48225,12 +48226,19 @@ public string loginID { /// [System.Xml.Serialization.XmlElementAttribute(Order=9)] - public string password { + public System.Security.SecureString password { get { return this.passwordField; } set { - this.passwordField = value; + if (value == null) + { + this.passwordField = null; + } + else { + this.passwordField = value; + this.passwordField.MakeReadOnly(); + } this.RaisePropertyChanged("password"); } } diff --git a/CyberSourceSamples/src/soap/SoapSample.cs b/CyberSourceSamples/src/soap/SoapSample.cs index 60ce620..ae72560 100644 --- a/CyberSourceSamples/src/soap/SoapSample.cs +++ b/CyberSourceSamples/src/soap/SoapSample.cs @@ -5,6 +5,7 @@ using CyberSource.Clients; using CyberSource.Clients.SoapServiceReference; using System.Security.Cryptography; +using System.Security; //using SoapSampleTransactions; @@ -386,7 +387,7 @@ public RequestMessage authRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -417,6 +418,22 @@ public RequestMessage authRequest() return request; } + private static SecureString convertToSecureString(string originalString) + { + if (originalString == null) + { + return null; + } + + var secureString = new SecureString(); + + foreach (char c in originalString) + secureString.AppendChar(c); + + secureString.MakeReadOnly(); + return secureString; + } + public RequestMessage authRevRequest() { RequestMessage request = new RequestMessage(); @@ -431,7 +448,7 @@ public RequestMessage authRevRequest() request.ccAuthReversalService = new CCAuthReversalService(); request.ccAuthReversalService.run = "true"; - request.ccAuthReversalService.authRequestID = "auth-request-id"; + request.ccAuthReversalService.authRequestID = "7195524478506344304010"; request.merchantReferenceCode = "your_merchant_reference_code"; @@ -595,7 +612,7 @@ public RequestMessage paymentNetworkTokenizationRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -656,7 +673,7 @@ public RequestMessage refundRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -732,7 +749,7 @@ public RequestMessage androidPayAuthRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -800,7 +817,7 @@ public RequestMessage applePayAuthRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -845,7 +862,6 @@ public RequestMessage saleRequest() // you would set a merchantID in each request. // this sample requests auth and capture - // Credit Card Authorization request.ccAuthService = new CCAuthService(); request.ccAuthService.run = "true"; @@ -867,7 +883,7 @@ public RequestMessage saleRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = "null@cybersource.com"; + billTo.email = convertToSecureString("null@cybersource.com"); billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; From bab074f812abde0c6913f3b9602da429b5394931 Mon Sep 17 00:00:00 2001 From: Gabriel Broadwin Nongsiej Date: Thu, 18 Jul 2024 16:15:12 +0530 Subject: [PATCH 4/5] Change for password field --- .../SoapServiceReference/Reference.cs | 38 ++++++++++++------- CyberSourceSamples/src/soap/SoapSample.cs | 12 +++--- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/CyberSource/Client/Service References/SoapServiceReference/Reference.cs b/CyberSource/Client/Service References/SoapServiceReference/Reference.cs index 69958f1..73c78ef 100644 --- a/CyberSource/Client/Service References/SoapServiceReference/Reference.cs +++ b/CyberSource/Client/Service References/SoapServiceReference/Reference.cs @@ -31953,7 +31953,7 @@ public partial class BillTo : object, System.ComponentModel.INotifyPropertyChang private string phoneNumberField; - private System.Security.SecureString emailField; + private string emailField; private string ipAddressField; @@ -32281,13 +32281,12 @@ public string phoneNumber { /// [System.Xml.Serialization.XmlElementAttribute(Order=20)] - public System.Security.SecureString email { + public string email { get { return this.emailField; } set { this.emailField = value; - this.emailField.MakeReadOnly(); this.RaisePropertyChanged("email"); } } @@ -48226,19 +48225,13 @@ public string loginID { /// [System.Xml.Serialization.XmlElementAttribute(Order=9)] - public System.Security.SecureString password { + public string password { get { - return this.passwordField; + return ConvertToUnsecureString(this.passwordField); } set { - if (value == null) - { - this.passwordField = null; - } - else { - this.passwordField = value; - this.passwordField.MakeReadOnly(); - } + this.passwordField = new System.Net.NetworkCredential(string.Empty, value).SecurePassword; + this.passwordField.MakeReadOnly(); this.RaisePropertyChanged("password"); } } @@ -49019,6 +49012,25 @@ protected void RaisePropertyChanged(string propertyName) { propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); } } + + public static string ConvertToUnsecureString(System.Security.SecureString secureString) + { + if (secureString == null) + { + return string.Empty; + } + + System.IntPtr unmanagedString = System.IntPtr.Zero; + try + { + unmanagedString = System.Runtime.InteropServices.Marshal.SecureStringToGlobalAllocUnicode(secureString); + return System.Runtime.InteropServices.Marshal.PtrToStringUni(unmanagedString); + } + finally + { + System.Runtime.InteropServices.Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString); + } + } } /// diff --git a/CyberSourceSamples/src/soap/SoapSample.cs b/CyberSourceSamples/src/soap/SoapSample.cs index ae72560..64ab9ed 100644 --- a/CyberSourceSamples/src/soap/SoapSample.cs +++ b/CyberSourceSamples/src/soap/SoapSample.cs @@ -387,7 +387,7 @@ public RequestMessage authRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -612,7 +612,7 @@ public RequestMessage paymentNetworkTokenizationRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -673,7 +673,7 @@ public RequestMessage refundRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -749,7 +749,7 @@ public RequestMessage androidPayAuthRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -817,7 +817,7 @@ public RequestMessage applePayAuthRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; @@ -883,7 +883,7 @@ public RequestMessage saleRequest() billTo.state = "CA"; billTo.postalCode = "94043"; billTo.country = "US"; - billTo.email = convertToSecureString("null@cybersource.com"); + billTo.email = "null@cybersource.com"; billTo.ipAddress = "10.7.111.111"; request.billTo = billTo; From 143ccec48b4837196425a17fea8fd35745d0880b Mon Sep 17 00:00:00 2001 From: gnongsie Date: Thu, 18 Jul 2024 20:25:57 +0530 Subject: [PATCH 5/5] Removed unnecessary code --- CyberSourceSamples/src/soap/SoapSample.cs | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/CyberSourceSamples/src/soap/SoapSample.cs b/CyberSourceSamples/src/soap/SoapSample.cs index 64ab9ed..c7cff81 100644 --- a/CyberSourceSamples/src/soap/SoapSample.cs +++ b/CyberSourceSamples/src/soap/SoapSample.cs @@ -5,8 +5,6 @@ using CyberSource.Clients; using CyberSource.Clients.SoapServiceReference; using System.Security.Cryptography; -using System.Security; -//using SoapSampleTransactions; namespace CyberSource.Samples @@ -418,22 +416,6 @@ public RequestMessage authRequest() return request; } - private static SecureString convertToSecureString(string originalString) - { - if (originalString == null) - { - return null; - } - - var secureString = new SecureString(); - - foreach (char c in originalString) - secureString.AppendChar(c); - - secureString.MakeReadOnly(); - return secureString; - } - public RequestMessage authRevRequest() { RequestMessage request = new RequestMessage(); @@ -448,7 +430,7 @@ public RequestMessage authRevRequest() request.ccAuthReversalService = new CCAuthReversalService(); request.ccAuthReversalService.run = "true"; - request.ccAuthReversalService.authRequestID = "7195524478506344304010"; + request.ccAuthReversalService.authRequestID = "auth-request-id"; request.merchantReferenceCode = "your_merchant_reference_code";