Skip to content

Commit 8a60c39

Browse files
authored
Merge pull request #3 from GovTechSG/development
Added functionality to handle json test cases.
2 parents f6a0c02 + ee1d97b commit 8a60c39

19 files changed

+1105
-108
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<Properties StartupConfiguration="{B6FD94F7-1689-4DAC-B823-0192E3CA3521}|Unit Tests">
2+
<MonoDevelop.Ide.Workbench ActiveDocument="ApiUtilLib/ApiAuthorization.cs">
3+
<Files>
4+
<File FileName="ApiUtilLibTest/TestDataTest.cs" Line="287" Column="1" />
5+
<File FileName="ApiUtilLibTest/L1SignatureTest.cs" Line="23" Column="72" />
6+
<File FileName="ApiUtilLib/ApiAuthorization.cs" Line="120" Column="13" />
7+
<File FileName="ApiUtilLibTest/CommonExtensions.cs" Line="121" Column="26" />
8+
<File FileName="ApiUtilLibTest/BaseService.cs" Line="122" Column="1" />
9+
<File FileName="ApiUtilLibTest/L2SignatureTest.cs" Line="37" Column="74" />
10+
<File FileName="development Status" />
11+
</Files>
12+
<Pads>
13+
<Pad Id="ProjectPad">
14+
<State name="__root__">
15+
<Node name="ApiSecuritySolution" expanded="True">
16+
<Node name="ApiUtilLib" expanded="True">
17+
<Node name="ApiAuthorization.cs" selected="True" />
18+
</Node>
19+
<Node name="ApiUtilLibTest" expanded="True" />
20+
</Node>
21+
</State>
22+
</Pad>
23+
<Pad Id="MonoDevelop.UnitTesting.TestPad">
24+
<State name="__root__">
25+
<Node name="ApiSecuritySolution" expanded="True">
26+
<Node name="ApiUtilLibTest" expanded="True">
27+
<Node name="ApexUtilLibTest" expanded="True">
28+
<Node name="TestDataTest" expanded="True">
29+
<Node name="GetL2Signature" selected="True" />
30+
</Node>
31+
</Node>
32+
</Node>
33+
</Node>
34+
</State>
35+
</Pad>
36+
</Pads>
37+
</MonoDevelop.Ide.Workbench>
38+
<MonoDevelop.Ide.Workspace ActiveConfiguration="Debug" />
39+
<MonoDevelop.Ide.DebuggingService.Breakpoints>
40+
<BreakpointStore>
41+
<Breakpoint file="/Users/nsearch/OneDrive/Projects/APEXCSharp/development/ApiUtilLib/ApiAuthorization.cs" relfile="ApiUtilLib/ApiAuthorization.cs" line="196" column="1" />
42+
<Breakpoint file="/Users/nsearch/OneDrive/Projects/APEXCSharp/development/ApiUtilLib/ApiAuthorization.cs" relfile="ApiUtilLib/ApiAuthorization.cs" line="179" column="1" />
43+
<Breakpoint file="/Users/nsearch/OneDrive/Projects/APEXCSharp/development/ApiUtilLibTest/TestDataTest.cs" relfile="ApiUtilLibTest/TestDataTest.cs" line="241" column="1" />
44+
<Breakpoint file="/Users/nsearch/OneDrive/Projects/APEXCSharp/development/ApiUtilLibTest/TestDataTest.cs" relfile="ApiUtilLibTest/TestDataTest.cs" line="281" column="1" />
45+
<Breakpoint file="/Users/nsearch/OneDrive/Projects/APEXCSharp/development/ApiUtilLibTest/TestDataTest.cs" relfile="ApiUtilLibTest/TestDataTest.cs" line="285" column="1" />
46+
</BreakpointStore>
47+
</MonoDevelop.Ide.DebuggingService.Breakpoints>
48+
<MonoDevelop.Ide.DebuggingService.PinnedWatches />
49+
<MonoDevelop.Ide.ItemProperties.ApiUtilLibTest PreferredExecutionTarget="MonoDevelop.Default" />
50+
<MultiItemStartupConfigurations />
51+
</Properties>

.vs/ApiSecuritySolution/xs/sqlite3/db.lock

Whitespace-only changes.
1.34 MB
Binary file not shown.
32 KB
Binary file not shown.
3.95 MB
Binary file not shown.

ApiUtilLib/ApiAuthorization.cs

Lines changed: 209 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44
using System.Security.Cryptography;
55
using System.Security.Cryptography.X509Certificates;
66
using System.Text;
7+
using ApexUtilLib;
8+
using System.Collections.Generic;
9+
using Newtonsoft.Json.Converters;
10+
using Newtonsoft.Json;
11+
using System.Linq;
12+
using Org.BouncyCastle;
13+
using Org.BouncyCastle.Crypto;
14+
using Org.BouncyCastle.OpenSsl;
15+
using Org.BouncyCastle.Crypto.Encodings;
16+
using Org.BouncyCastle.Crypto.Engines;
17+
using Org.BouncyCastle.Crypto.Parameters;
18+
using Org.BouncyCastle.Security;
719

820
namespace ApiUtilLib
921
{
@@ -101,12 +113,11 @@ public static RSACryptoServiceProvider PrivateKeyFromP12(string certificateFileN
101113
{
102114
Logger.LogEnterExit(LoggerBase.Args(certificateFileName, "***password***"));
103115

116+
104117
var privateCert = new X509Certificate2(System.IO.File.ReadAllBytes(certificateFileName), password, X509KeyStorageFlags.Exportable);
105118

106119
var OriginalPrivateKey = (RSACryptoServiceProvider)privateCert.PrivateKey;
107120

108-
// Transfer the private key to overcome the following error...
109-
// System.Security.Cryptography.CryptographicException "Invalid algorithm specified"
110121
if (Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix)
111122
{
112123
return OriginalPrivateKey;
@@ -120,6 +131,127 @@ public static RSACryptoServiceProvider PrivateKeyFromP12(string certificateFileN
120131
}
121132
}
122133

134+
public static string GetL2SignatureFromPEM(string filename, string message, string passPhrase)
135+
{
136+
Logger.LogEnterExit(LoggerBase.Args(filename, "***password***"));
137+
string result = null;
138+
try
139+
{
140+
using (FileStream fs = File.OpenRead(filename))
141+
{
142+
AsymmetricCipherKeyPair keyPair;
143+
var obj = GetRSAProviderFromPem(File.ReadAllText(filename).Trim(), passPhrase);
144+
byte[] bytes = Encoding.UTF8.GetBytes(message);
145+
146+
using (var reader = File.OpenText(filename))
147+
keyPair = (AsymmetricCipherKeyPair)new PemReader(reader, new PasswordFinder(passPhrase)).ReadObject();
148+
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
149+
150+
decryptEngine.Init(false, keyPair.Private);
151+
var str = obj.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
152+
153+
result = System.Convert.ToBase64String(str);
154+
}
155+
}
156+
catch (Exception ex)
157+
{
158+
throw ex;
159+
}
160+
return result;
161+
}
162+
163+
public static RSACryptoServiceProvider ImportPrivateKey(string pem)
164+
{
165+
PemReader pr = new PemReader(new StringReader(pem));
166+
AsymmetricCipherKeyPair KeyPair = (AsymmetricCipherKeyPair)pr.ReadObject();
167+
RSAParameters rsaParams = DotNetUtilities.ToRSAParameters((RsaPrivateCrtKeyParameters)KeyPair.Private);
168+
169+
RSACryptoServiceProvider csp = new RSACryptoServiceProvider();
170+
csp.ImportParameters(rsaParams);
171+
return csp;
172+
}
173+
174+
175+
public static X509Certificate2 LoadCertificateFile(string filename, string passPhrase)
176+
{
177+
X509Certificate2 x509 = null;
178+
try
179+
{
180+
using (FileStream fs = File.OpenRead(filename))
181+
{
182+
AsymmetricCipherKeyPair keyPair;
183+
var obj = GetRSAProviderFromPem(File.ReadAllText(filename).Trim(), passPhrase);
184+
byte[] bytes = Encoding.UTF8.GetBytes("message");
185+
186+
using (var reader = File.OpenText(filename))
187+
keyPair = (AsymmetricCipherKeyPair)new PemReader(reader, new PasswordFinder(passPhrase)).ReadObject();
188+
var decryptEngine = new Pkcs1Encoding(new RsaEngine());
189+
190+
decryptEngine.Init(false, keyPair.Private);
191+
var str = obj.SignData(bytes, CryptoConfig.MapNameToOID("SHA256"));
192+
193+
var base64 = System.Convert.ToBase64String(str);
194+
195+
var privateCert = new X509Certificate2(base64, passPhrase, X509KeyStorageFlags.Exportable);
196+
}
197+
}
198+
catch (Exception ex)
199+
{
200+
throw ex;
201+
}
202+
return x509;
203+
}
204+
205+
206+
public static RSACryptoServiceProvider GetRSAProviderFromPem(String pemstr, string password)
207+
{
208+
CspParameters cspParameters = new CspParameters();
209+
cspParameters.KeyContainerName = "MyKeyContainer";
210+
RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider(cspParameters);
211+
212+
Func<RSACryptoServiceProvider, RsaKeyParameters, RSACryptoServiceProvider> MakePublicRCSP = (RSACryptoServiceProvider rcsp, RsaKeyParameters rkp) =>
213+
{
214+
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp);
215+
rcsp.ImportParameters(rsaParameters);
216+
return rsaKey;
217+
};
218+
219+
Func<RSACryptoServiceProvider, RsaPrivateCrtKeyParameters, RSACryptoServiceProvider> MakePrivateRCSP = (RSACryptoServiceProvider rcsp, RsaPrivateCrtKeyParameters rkp) =>
220+
{
221+
RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp);
222+
rcsp.ImportParameters(rsaParameters);
223+
return rsaKey;
224+
};
225+
IPasswordFinder pwd;
226+
PemReader reader;
227+
reader = new PemReader(new StringReader(pemstr), new PasswordFinder(password));
228+
object kp = reader.ReadObject();
229+
230+
if (kp.GetType().GetProperty("Private") != null)
231+
{
232+
return MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)(((AsymmetricCipherKeyPair)kp).Private));
233+
}
234+
else
235+
{
236+
return MakePublicRCSP(rsaKey, (RsaKeyParameters)kp);
237+
}
238+
239+
240+
}
241+
242+
243+
244+
public static byte[] PEM(string type, byte[] data)
245+
{
246+
string pem = Encoding.ASCII.GetString(data);
247+
string header = String.Format("-----BEGIN {0}-----", type);
248+
string footer = String.Format("-----END {0}-----", type);
249+
int start = pem.IndexOf(header) + header.Length;
250+
int end = pem.IndexOf(footer, start);
251+
string base64 = pem.Substring(start, (end - start));
252+
return Convert.FromBase64String(base64);
253+
}
254+
123255
public static RSACryptoServiceProvider PublicKeyFromCer(string certificateFileName)
124256
{
125257
Logger.LogEnterExit(LoggerBase.Args(certificateFileName));
@@ -159,57 +291,69 @@ string authPrefix
159291
, string timestamp
160292
, string version)
161293
{
162-
Logger.LogEnter(LoggerBase.Args(authPrefix, signatureMethod, appId, siteUri, httpMethod, formList, nonce, timestamp));
163-
164-
authPrefix = authPrefix.ToLower();
165-
166-
// make sure that the url are valid
167-
if (siteUri.Scheme != "http" && siteUri.Scheme != "https")
294+
try
168295
{
169-
throw new System.NotSupportedException("Support http and https protocol only.");
170-
}
296+
Logger.LogEnter(LoggerBase.Args(authPrefix, signatureMethod, appId, siteUri, httpMethod, formList, nonce, timestamp));
171297

172-
// make sure that the port no and querystring are remove from url
173-
var url = string.Format("{0}://{1}{2}", siteUri.Scheme, siteUri.Host, siteUri.AbsolutePath);
174-
Logger.LogInformation("url:: {0}", url);
298+
authPrefix = authPrefix.ToLower();
175299

176-
// helper calss that handle parameters and form fields
177-
ApiList paramList = new ApiList();
300+
// make sure that the url are valid
301+
if (siteUri.Scheme != "http" && siteUri.Scheme != "https")
302+
{
303+
throw new System.NotSupportedException("Support http and https protocol only.");
304+
}
178305

179-
// process QueryString from url by transfering it to paramList
180-
if (siteUri.Query.Length > 1)
181-
{
182-
var queryString = siteUri.Query.Substring(1); // remove the ? from first character
183-
Logger.LogInformation("queryString:: {0}", queryString);
306+
// make sure that the port no and querystring are remove from url
307+
var url = string.Format("{0}://{1}{2}", siteUri.Scheme, siteUri.Host, siteUri.AbsolutePath);
308+
Logger.LogInformation("url:: {0}", url);
184309

185-
var paramArr = queryString.Split('&');
186-
foreach (string item in paramArr)
187-
{
188-
var itemArr = item.Split('=');
189-
paramList.Add(itemArr[0], System.Net.WebUtility.UrlDecode(itemArr[1]));
190-
}
310+
// helper calss that handle parameters and form fields
311+
ApiList paramList = new ApiList();
191312

192-
Logger.LogInformation("paramList:: {0}", paramList);
193-
}
313+
// process QueryString from url by transfering it to paramList
314+
if (siteUri.Query.Length > 1)
315+
{
316+
var queryString = siteUri.Query.Substring(1); // remove the ? from first character
317+
Logger.LogInformation("queryString:: {0}", queryString);
318+
319+
var paramArr = queryString.Split('&');
320+
foreach (string item in paramArr)
321+
{
322+
string key = null;
323+
string val = null;
324+
var itemArr = item.Split('=');
325+
key = itemArr[0];
326+
if(itemArr.Length>1)
327+
val = itemArr[1];
328+
paramList.Add(key, System.Net.WebUtility.UrlDecode(val));
329+
}
330+
331+
Logger.LogInformation("paramList:: {0}", paramList);
332+
}
194333

195-
// add the form fields to paramList
196-
if (formList != null && formList.Count > 0)
197-
{
198-
paramList.AddRange(formList);
199-
}
334+
// add the form fields to paramList
335+
if (formList != null && formList.Count > 0)
336+
{
337+
paramList.AddRange(formList);
338+
}
200339

201-
paramList.Add(authPrefix + "_timestamp", timestamp);
202-
paramList.Add(authPrefix + "_nonce", nonce);
203-
paramList.Add(authPrefix + "_app_id", appId);
204-
paramList.Add(authPrefix + "_signature_method", signatureMethod.ToString());
205-
paramList.Add(authPrefix + "_version", version);
340+
paramList.Add(authPrefix + "_timestamp", timestamp);
341+
paramList.Add(authPrefix + "_nonce", nonce);
342+
paramList.Add(authPrefix + "_app_id", appId);
343+
paramList.Add(authPrefix + "_signature_method", signatureMethod.ToString());
344+
paramList.Add(authPrefix + "_version", version);
206345

207-
string baseString = httpMethod.ToString() + "&" + url + "&" + paramList.ToString();
346+
string baseString = httpMethod.ToString() + "&" + url + "&" + paramList.ToString();
208347

209-
Logger.LogDebug("BaseString:: {0}", baseString);
348+
Logger.LogDebug("BaseString:: {0}", baseString);
210349

211-
Logger.LogExit(LoggerBase.Args(baseString));
212-
return baseString;
350+
Logger.LogExit(LoggerBase.Args(baseString));
351+
return baseString;
352+
}
353+
catch (Exception ex)
354+
{
355+
throw ex;
356+
}
213357
}
214358

215359
public static long NewTimestamp()
@@ -228,12 +372,12 @@ public static string NewNonce()
228372
{
229373
// Buffer storage.
230374
data = new byte[8];
231-
232375
// Fill buffer.
233376
rng.GetBytes(data);
234377
}
235378

236379
Logger.LogEnterExit(LoggerBase.Args(nonce.ToString()));
380+
237381
return System.Convert.ToBase64String(data);
238382
}
239383

@@ -283,14 +427,14 @@ string realm
283427
var tokenList = new ApiList();
284428

285429
tokenList.Add("realm", realm);
286-
tokenList.Add(authPrefix + "_timestamp", timestamp);
287-
tokenList.Add(authPrefix + "_nonce", nonce);
288430
tokenList.Add(authPrefix + "_app_id", appId);
431+
tokenList.Add(authPrefix + "_nonce", nonce);
289432
tokenList.Add(authPrefix + "_signature_method", signatureMethod.ToString());
433+
tokenList.Add(authPrefix + "_timestamp", timestamp);
290434
tokenList.Add(authPrefix + "_version", version);
291435
tokenList.Add(authPrefix + "_signature", base64Token);
292436

293-
string authorizationToken = string.Format("{0} {1}", authPrefix.Substring(0, 1).ToUpperInvariant() + authPrefix.Substring(1), tokenList.ToString(",", false, true));
437+
string authorizationToken = string.Format("{0} {1}", authPrefix.Substring(0, 1).ToUpperInvariant() + authPrefix.Substring(1), tokenList.ToString(", ", false, true));
294438

295439
Logger.LogDebug("Token :: {0}", authorizationToken);
296440

@@ -426,5 +570,24 @@ public static void InitiateSSLTrust()
426570
Console.WriteLine("{0}", ex);
427571
}
428572
}
573+
574+
private class PasswordFinder : IPasswordFinder
575+
{
576+
private string password;
577+
578+
public PasswordFinder(string password)
579+
{
580+
this.password = password;
581+
}
582+
583+
584+
public char[] GetPassword()
585+
{
586+
return password.ToCharArray();
587+
}
588+
}
589+
429590
}
591+
592+
430593
}

0 commit comments

Comments
 (0)