how do i sign data in C# using x509Certificate2? - c#

I'm working on an application where I will have to sign data (a string) which would then be used later in the application. The problem is, each time I try it, the output comes out as an empty string. the code that does the signing is written below...
private string SignData(string dataToSign)
{
log.Info("About to sign data");
string certPath = BankWebUtil.CertPath;
string certPassword = BankWebUtil.CertPassword;
string result = "";
this.log.InfoFormat("The certificate path is : {0}", certPath);
this.log.InfoFormat("The certificate password is : {0}", certPassword);
X509Certificate2 x509Certificate2 = null;
try
{
this.log.Info("Trying to get the certificate object with password");
x509Certificate2 = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.Exportable);
if (x509Certificate2 == null)
{
throw new Exception("Trying to get the certificate object with password returned null");
}
}
catch
{
this.log.Info("Trying to get the certificate object with only filename");
x509Certificate2 = new X509Certificate2(certPath);
}
finally
{
try
{
if (x509Certificate2 != null)
{
byte[] hash = new SHA256Managed().ComputeHash(new ASCIIEncoding().GetBytes(dataToSign));
byte[] rgbHash = hash;
string str = CryptoConfig.MapNameToOID("SHA256");
if (x509Certificate2.PrivateKey == null)
{
throw new Exception("Certificate PrivateKey is null");
}
var certifiedRSACryptoServiceProvider = x509Certificate2.PrivateKey as RSACryptoServiceProvider;
RSACryptoServiceProvider defaultRSACryptoServiceProvider = new RSACryptoServiceProvider();
defaultRSACryptoServiceProvider.ImportParameters(certifiedRSACryptoServiceProvider.ExportParameters(true));
byte[] inArray = defaultRSACryptoServiceProvider.SignHash(rgbHash, str);
result = Convert.ToBase64String(inArray);
}
else
{
throw new Exception("Certificate object is null");
}
}
catch (Exception ex)
{
this.log.Error(ex.Message,ex);
}
}
return result;
}
This is how I intend to test the code.
var customerRef = "200937943";
var customerName = "KAWEESI MARTIN";
var customerTel = "256774018257";
var customerType = "POSTPAID";
var vendorTranId = "UMEME280918200001";
var VendorCode = "Vendor Code";
var pPassword = "ECO-TEST";
var paymentDate = "28/09/2018";
var paymentType = "2";
var teller = "899";
var tranAmount = "48445.51";
var tranNarration = "BC|UMEME280918200001|200937943|0001";
var tranType = "Cash";
var digitalSignature = SignData(customerRef + customerName + customerTel + customerType + vendorTranId + VendorCode +
pPassword + paymentDate + paymentType + teller + tranAmount + tranNarration + tranType);
the variable "digitalSignature" comes out as an empty string... please help me!

Related

BouncyCastle (bc-sharp) decode DER formatted signature

How do I decode DER-formatted detached signature using BouncyCastle bc-sharp? For PEM-formatted signature I do it like this:
public static bool VerifyDetachedSignature(byte[] fileRawBytes, string sign)
{
try
{
var signatureFileRawBytes = Convert.FromBase64String(sign);
var cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), signatureFileRawBytes);
var signers = cms.GetSignerInfos();
var certificates = cms.GetCertificates("Collection");
var signerInfos = signers.GetSigners();
foreach (SignerInformation info in signerInfos)
{
var certList = new ArrayList(certificates.GetMatches(info.SignerID));
var cert = (X509Certificate)certList[0];
if (cert == null) throw new NullReferenceException();
var publicKey = cert.GetPublicKey();
info.Verify(publicKey);
}
return true;
}
catch (Exception exception)
{
return false;
}
}
On rare ocasions I need to verify DER-formatted signature. It appears I just need to covert string to byte array, like this:
public static bool VerifyDetachedSignature(byte[] fileRawBytes, string sign)
{
try
{
byte[] signatureFileRawBytes;
try
{
signatureFileRawBytes = Convert.FromBase64String(sign);
}
catch (FormatException)
{
signatureFileRawBytes = Encoding.ASCII.GetBytes(sign);
}
var cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), signatureFileRawBytes);
var signers = cms.GetSignerInfos();
var certificates = cms.GetCertificates("Collection");
var signerInfos = signers.GetSigners();
foreach (SignerInformation info in signerInfos)
{
var certList = new ArrayList(certificates.GetMatches(info.SignerID));
var cert = (X509Certificate)certList[0];
if (cert == null) throw new NullReferenceException();
var publicKey = cert.GetPublicKey();
info.Verify(publicKey);
}
return true;
}
catch (Exception exception)
{
return false;
}
}
In this case I get an exception on that line:
var cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), signatureFileRawBytes);
Org.BouncyCastle.Cms.CmsException
HResult=0x80131500
Message=IOException reading content.
Source=BouncyCastle
StackTrace:
at Org.BouncyCastle.Cms.CmsUtilities.ReadContentInfo(Asn1InputStream aIn)
at Org.BouncyCastle.Cms.CmsUtilities.ReadContentInfo(Stream input)
at Org.BouncyCastle.Cms.CmsSignedData..ctor(CmsProcessable signedContent, Byte[] sigBlock)
at backend.Helpers.CryptoHelper.VerifyDetachedSignature(Byte[] fileRawBytes, String sign) in C:\Projects\[...]\Helpers\CryptoHelper.cs:line 107
This exception was originally thrown at this call stack:
[External Code]
Inner Exception 1:
EndOfStreamException: DEF length 63 object truncated by 2
Any thoughts or suggestions on how to decode DER-signature?
It turned out the problem was not related to BouncyCastle. The problem was that I read binary data to a string variable and lose data. When i passed signature as byte array to VerifyDetachedSignature(byte[] fileRawBytes, byte[] sign) method it worked perfectly like this:
public static bool VerifyDetachedSignature(byte[] fileRawBytes, byte[] sign)
{
try
{
CmsSignedData cms;
try
{
cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), sign);
}
catch (CmsException)
{
var strSign = System.Text.Encoding.ASCII.GetString(sign);
var decodedSignRawBytes = Convert.FromBase64String(strSign);
cms = new CmsSignedData(new CmsProcessableByteArray(fileRawBytes), decodedSignRawBytes);
}
var signers = cms.GetSignerInfos();
var certificates = cms.GetCertificates("Collection");
var signerInfos = signers.GetSigners();
foreach (SignerInformation info in signerInfos)
{
var certList = new ArrayList(certificates.GetMatches(info.SignerID));
var cert = (X509Certificate)certList[0];
if (cert == null) throw new NullReferenceException();
var publicKey = cert.GetPublicKey();
info.Verify(publicKey);
}
return true;
}
catch (Exception)
{
return false;
}
}
Hope this helps someone to not make the same mistake.

How to fix Amazon.Rekognition.AmazonRekognitionException?

I am getting AmazonRekognitionException as below when trying to run CompareFacesResponse, I am stuck, what should I do or check?
Amazon.Rekognition.AmazonRekognitionException: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details. ---> Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type 'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown
AWS credentials access key and secret are checked and correct
public static async Task<Tuple<bool, string>> Rekognition_Compare_Faces(string _source, string _target, string _bucketName)
{
const string HOSTNAME = "https://rekognition.ap-southeast-1.amazonaws.com/";
const string ACCESS_KEY = "my_access_key";
const string ACCESS_SECRET = "my_secret_key";
float _similarityThreshold = 70F;
bool _ret = false;
string _confidence = string.Empty;
try
{
AmazonRekognitionConfig _config = new AmazonRekognitionConfig();
_config.ServiceURL = HOSTNAME + _bucketName;
AmazonRekognitionClient _rekognitionClient = new AmazonRekognitionClient(ACCESS_KEY, ACCESS_SECRET, _config);
Amazon.Rekognition.Model.Image _imageSource = new Amazon.Rekognition.Model.Image();
Amazon.Rekognition.Model.Image _imageTarget = new Amazon.Rekognition.Model.Image();
Amazon.Rekognition.Model.S3Object _s3_source = new Amazon.Rekognition.Model.S3Object { Bucket = _bucketName, Name = _source };
Amazon.Rekognition.Model.S3Object _s3_target = new Amazon.Rekognition.Model.S3Object { Bucket = _bucketName, Name = _target };
CompareFacesRequest _compareFacesRequest = new CompareFacesRequest()
{
SourceImage = new Amazon.Rekognition.Model.Image
{
S3Object = new Amazon.Rekognition.Model.S3Object
{
Bucket = HOSTNAME + _bucketName,
Name = _source
}
},
TargetImage = new Amazon.Rekognition.Model.Image
{
S3Object = new Amazon.Rekognition.Model.S3Object
{
Bucket = HOSTNAME + _bucketName,
Name = _target
}
},
SimilarityThreshold = _similarityThreshold
};
// IT THROWN HERE!!
CompareFacesResponse _compareFacesResponse = await _rekognitionClient.CompareFacesAsync(_compareFacesRequest);
// Display results
foreach (CompareFacesMatch match in _compareFacesResponse.FaceMatches)
{
ComparedFace face = match.Face;
BoundingBox position = face.BoundingBox;
_confidence = match.Similarity.ToString(AppSettings.Decimal_Number_Format) + "%";
_ret = true;
}
}
catch (Exception ex) { await ClsMain.SaveLog("AWS.Compare_Faces: " + ex.ToString()); }
finally { }
return await Task.FromResult(new Tuple<bool, string>(_ret, _confidence));
}
has anybody experience on this?
thanks a lot in advance
Regards
Don
I had the same error.
I tried adding RegionEndpoint = RegionEndpoint.EUWest1 to my AmazonRekognitionConfig so it now looks like this:
var config = new AmazonRekognitionConfig
{
ServiceURL = $"https://rekognition.ap-southeast-1.amazonaws.com/{_awsSettings.BucketName}",
RegionEndpoint = RegionEndpoint.EUWest1
};
var client = new AmazonRekognitionClient(_awsSettings.AccessKey, _awsSettings.Secret, config);
This fixed the problem for me.

Umbraco Decrypting using MachineKey Encoding in C#

I want to first encrypt some nodes in Umbraco's content editor. The code below is the one I use for encryption. I use MachineKey.Protect for this.
try
{
MailMessage message1 = new MailMessage();
MailMessage message2 = new MailMessage();
SmtpClient client = new SmtpClient();
string AfsenderEmail = model.Email;
string AfsenderNavn = model.Name;
string toAddress = Umbraco.Content(rootNode.Id).mailDerSendesTil;
message1.From = new MailAddress(toAddress);
message2.From = new MailAddress(toAddress);
message1.Subject = $"{Umbraco.Content(rootNode.Id).overskriftPaaDenMailViFaar}";
message1.Subject = message1.Subject.Replace("AfsenderEmail", AfsenderEmail);
message1.Subject = message1.Subject.Replace("AfsenderNavn", AfsenderNavn);
message1.Body = $"{Umbraco.Content(rootNode.Id).beskedViFaarNaarBeskedenSendes}";
message1.Body = message1.Body.Replace("AfsenderEmail", AfsenderEmail);
message1.Body = message1.Body.Replace("AfsenderNavn", AfsenderNavn);
message1.To.Add(new MailAddress(toAddress));
client.Send(message1);
message2.Subject = $"{Umbraco.Content(rootNode.Id).overskriftPaaMeddelelsenAfsenderenFaar}";
message2.Subject = message2.Subject.Replace("AfsenderEmail", AfsenderEmail);
message2.Subject = message2.Subject.Replace("AfsenderNavn", AfsenderNavn);
message2.Body = $"{Umbraco.Content(rootNode.Id).beskedAfsenderenFaarNaarBeskedenSendes}";
message2.Body = message2.Body.Replace("AfsenderEmail", AfsenderEmail);
message2.Body = message2.Body.Replace("AfsenderNavn", AfsenderNavn);
message2.To.Add(new MailAddress(AfsenderEmail));
client.Send(message2);
var beskederNode = Umbraco.TypedContentAtRoot().FirstOrDefault(x => x.ContentType.Alias.Equals("Besked"));
var encryptName = MachineKey.Protect(Encoding.ASCII.GetBytes(model.Name));
var encryptEmail = MachineKey.Protect(Encoding.ASCII.GetBytes(model.Email));
var encryptMessage = MachineKey.Protect(Encoding.ASCII.GetBytes(model.Message));
string nameEncrypted = Encoding.ASCII.GetString(encryptName);
string emailEncrypted = Encoding.ASCII.GetString(encryptEmail);
string messageEncrypted = Encoding.ASCII.GetString(encryptMessage);
var newContent = contentService.CreateContent(nameEncrypted, beskederNode.Id, "mails");
newContent.SetValue("fra", nameEncrypted);
newContent.SetValue("eMail", emailEncrypted);
newContent.SetValue("besked", messageEncrypted);
var result = contentService.SaveAndPublishWithStatus(newContent);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
catch (System.Exception ex)
{
Log.Error("Contact Form Error", ex);
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
}
This is where I Try to decrypt my code again. It throws an exception (System.Security.Cryptography.CryptographicException: 'Error occurred during a cryptographic operation.') when I call MachineKey.Unprotect(nameDecrypted) and I cannnot find my mistake. I think it maybe has somethimg to do with my Encoding and Decoding?
private void EditorModelEventManager_SendingContentModel(System.Web.Http.Filters.HttpActionExecutedContext sender, EditorModelEventArgs<Umbraco.Web.Models.ContentEditing.ContentItemDisplay> e)
{
var node = e.Model.Properties.ToList();
if (e.Model.IsChildOfListView && e.Model.ContentTypeAlias == "mails")
{
string nameDecrypt = node.Where(x => x.Alias.ToLower() == "fra").Select(x => x.Value).First().ToString();
Byte[] nameDecrypted = Encoding.ASCII.GetBytes(nameDecrypt);
var name = e.Model.Properties.FirstOrDefault(x => x.Alias.ToLower() == "fra");
Byte[] decryptName = MachineKey.Unprotect(nameDecrypted);
string nameReady = Encoding.ASCII.GetString(decryptName);
name.Value = $"{nameReady}";
}
}
}
}
I found a solution. Instead of using Encoding.ASCII.GetString(), I used Convert.FromBase64String().

Getting users from active directory using openldap c#

I'm a newbie using c# and i need to create an extension that goes to a directory and retrieves info about the users like username, name and email.
This is the login validation method that i created and it's working.
public void MssValidateUserLDAP(string ssHostname, string ssBaseDN, string ssUsername, string ssPassword, out bool ssOk, out string ssErrorMessage) {
ssOk = false;
ssErrorMessage = string.Empty;
String ssBaseRDN = string.Empty; // stores user RDN for authentication
LdapConnection connection = new LdapConnection(ssHostname);
connection.AuthType = AuthType.Basic;
try
{
SearchRequest searchRequest = new SearchRequest();
// Search parameters
searchRequest.Scope = System.DirectoryServices.Protocols.SearchScope.OneLevel;
searchRequest.DistinguishedName = ssBaseDN;
searchRequest.Filter = ssUsername;
// cast the returned directory response as a SearchResponse object
SearchResponse searchResponse = (SearchResponse)connection.SendRequest(searchRequest);
// enumerate the entries in the search response
foreach (SearchResultEntry entry in searchResponse.Entries)
{
ssBaseRDN = entry.DistinguishedName;
ssOk = true;
}
if (ssBaseRDN != "")
{
connection.Bind(new NetworkCredential(ssBaseRDN, ssPassword));
}
else { ssOk = false; ssErrorMessage = "User not found"; }
}
catch (Exception e)
{
ssErrorMessage = e.GetType().Name + " " + e.Message;
ssOk = false;
}
}
This is what i was able to do, but it's not working and i can't find the reason behind that. Any help would be appreciated!
public void MssSearch(string ssUsername, string ssPassword, string ssPath, out RLUserRecordList ssUsers, out string ssErrorMessage) {
ssErrorMessage = "";
ssUsers = new RLUserRecordList(null);
try
{
RLUserRecordList aux = new RLUserRecordList();
DirectoryEntry rootEntry = new DirectoryEntry(ssPath,ssUsername,ssPassword);
DirectorySearcher searcher = new DirectorySearcher(rootEntry);
foreach(SearchResult result in searcher.FindAll())
{
RCUserRecord u = new RCUserRecord(Convert.ToString(result.Properties["cn"][0]));
aux.Append(u);
}
ssUsers = aux;
}
catch (Exception e){
ssErrorMessage = e.GetType().Name + " " + e.Message;
}
} // MssSearch

trying to send email request but i get exception

I am trying to create and send an email request in crm2011. I have the email, but when I try to send it I get an exception:
email With Id = 00000000-0000-0000-0000-000000000000 Does Not Exist.
Here's my code:
OrganizationServiceProxy p = new OrganizationServiceProxy(
new Uri(""), null, ccr, null);
WhoAmIRequest systemUserRequest = new WhoAmIRequest();
WhoAmIResponse systemUserResponse = (WhoAmIResponse)p.Execute(systemUserRequest);
Guid _userId = systemUserResponse.UserId;
Entity email = new Entity("email");
email.Attributes.Add("subject", "test");
Entity[] To = new Entity[1];
To[0] = new Entity("activityparty");
To[0]["partyid"] = new EntityReference("contact", new Guid("some guidid"));
email.Attributes.Add("to", To);
Entity[] From = new Entity[1];
From[0] = new Entity("activityparty");
From[0]["partyid"] = new EntityReference("systemuser", _userId);
email.Attributes.Add("from", From);
try
{
Guid emailGuid = p.Create(email);
}
catch (Exception e)
{
Console.WriteLine("error " + e.Message);
Console.ReadLine();
}
OrganizationRequest request = new OrganizationRequest() { RequestName = "SendEmail" };
request["EmailId"] = email.Id;
request["TrackingToken"] = "";
request["IssueSend"] = true;
// THE CODE FAILS HERE:
OrganizationResponse rsp = p.Execute(request);
The main error is in this line:
request["EmailId"] = email.Id;
when you create the email, the Id property is not filled inside the record but the Guid is inside the variable emailGuid
I suggest to change the code in this way :
try
{
Guid emailGuid = p.Create(email);
OrganizationRequest request = new OrganizationRequest() { RequestName = "SendEmail" };
request["EmailId"] = emailGuid; // now is the right variable
request["TrackingToken"] = "";
request["IssueSend"] = true;
OrganizationResponse rsp = p.Execute(request);
}
catch (Exception e)
{
Console.WriteLine("error " + e.Message);
Console.ReadLine();
}

Categories