Can't find certificate by serial number - c#

I've imported my certificates to Personal -> Certificates.
I use the following lines of code to find my certificate by serial number but I can't:
public X509Certificate2Collection FindCerts(string serialNumber)
{
var searchType = X509FindType.FindBySerialNumber;
var storeName = "MY";
var certificatesStore = new X509Store(storeName, StoreLocation.LocalMachine);
certificatesStore.Open(OpenFlags.OpenExistingOnly);
var matchingCertificates = certificatesStore.Certificates.Find(searchType, serialNumber, true);
certificatesStore.Close();
return matchingCertificates;
}
Could you please tell me why I can't find my cert even though it is in certificatesStore.Certificates list?
Note: my certs were created by Go Daddy

I've fixed this problem by entering the serial number instead copying from the property window. I don't know why when copying from this window, it contains a strange character on the beginning of the serial number.

Since I came across this issue too, I tried to make a workaround to be able to copy paste the value from the certmgr.msc
A summary of what I did :
// The value below is pasted from certmgr.msc
var sslCertificateSerialNumber="‎47 9f da c4 ad d7 33 a6 4c ad 54 d3 d9 95 67 1c";
// Remove all non allowed characters that entered the value while copy/paste
var rgx = new Regex("[^a-fA-F0-9]");
var serial = rgx.Replace(sslCertificateSerialNumber, string.Empty).ToUpper();
Now I found the correct certificate with a copy/pasted value.

If you are sure about the presence of certificate in machine store, can you try giving the third parameter to Find() as 'false'?

The certificate serial number is a binary data sequence which denotes a big int of unlimited length. If you saw the text somewhere, this can mean that either the text was written as serial OR (which is more likely) that you are seeing either Base64- or Base16- encoded binary serial. In the latter case you won't find it in straightforward way - you need to decode the serial and try that way.

If what you are trying to extract are the certificate/s issued by GoDaddy,you may use this:
var certificateStore= new X509Store(StoreLocation.LocalMachine);
certificateStore.Open(OpenFlags.ReadOnly);
var certificates = certificateStore.Certificates;
foreach (var certificate in certificateStore)
{
if (certificate.Issuer.Contains("GoDaddy"))
{

Make sure that serialNumber is uppercase string. I had some problems with finding certificates when sn was in lowercase. Also remove whitespaces if you copy sn from the certificate's details window

If you copy from the windows certificate property window, you may accidentally copy some extra invisible characters across, which will break your serial number search.
See this question for more information:
X509 store can not find certificate by SerialNumber

I ran into a similar issue yesterday and spent a number of hours trying to find out why on earth the existing certificate was not being found. It seems that the Certificates.Find method executes a case-sensitive search. I took the recursive approach using String.Compare.
X509Certificate2 storedCert = null;
for (int i = 0; i < store.Certificates.Count; i++)
{
if (String.Compare(store.Certificates[i].SerialNumber, MySerialNum, true) == 0)
{
storedCert = store.Certificates[i];
break;
}
}

To find by serial number, starting from the serial as reported by the mmc snap-in, remove all whitespace and uppercase all alphas. Worked for me. This will give you something like...
008CC59B72BE954F93F1435F6B86227600
As others have said, pay super attention to the "invisible special character" at the start of the string. Copy into and out of notepad to strip it. The same goes for all fields copied out of the cert property window.

Related

Selenium SendKeys() with Chromedriver uses Clipboard Content instead of "#" Character in email adress

Im trying to write an email-address into an input field using Selenium and ChromeDriver in C#. Nothing spectacular so far. But in case of strings, containing "#"characters it is sending the content of the clipboard instead of this character.
For example:
The Content of the Clipboard ist "####MYCLIPBOARDCONTENT######" Copied by Ctrl+C
Execution of the Lines
var input = _webDriver.FindElement(By.Id(id));
input.Clear();
input.SendKeys("abc#def.test");
Is leading to this in the UI
Can anyone confirm this behaviour? How to deal with it? I don't want to bypass this by some strange hacks.
Use action chains to build "AltGr + Q".
var actions = new OpenQA.Selenium.Interactions.Actions(driver);
actions.KeyDown(Keys.Control).KeyDown(Keys.Alt); //press Alt
actions.SendKeys("Q"); //press Q
actions.KeyUp(Keys.Control).KeyUp(Keys.Alt); //Release key
actions.Build().Perform();
Actually i don't want to use these hacks for such basic string operations.
But i found the issue by myself now. It was related to my language settings in Windows.
I was using 1. EN-US, 2. DE-DE, and 3. EN-HR. I removed the third one. Now it is working as expected.
Probably it's because a non us keyboard.
import pyperclip as pc
AtSign = "#"
pc.copy(AtSign)
AtSign = pc.paste()
print(AtSign)

Predicting length of UserManager.GenerateUserTokenAsync tokens (via DataProtectorTokenProvider)

I'm using ASP.NET Core 3.1, with some custom logic that reuses ASP.NET Core Identity's UserManager<TUser> class. I want to reuse its ability to GenerateUserTokenAsync(...), the same type of token also used in e.g. e-mail confirmations. For my application's purpose, I need to know the maximum length for generated tokens.
I've done the following research:
UserManager<TUser>.GenerateUserTokenAsync(...) calls GenerateAsync on the injected provider
in my case that is the DataProtectorTokenProvider<TUser> which will generate tokens like this:
var ms = new MemoryStream();
var userId = await manager.GetUserIdAsync(user);
using (var writer = ms.CreateWriter())
{
writer.Write(DateTimeOffset.UtcNow);
writer.Write(userId);
writer.Write(purpose ?? "");
string stamp = null;
if (manager.SupportsUserSecurityStamp)
{
stamp = await manager.GetSecurityStampAsync(user);
}
writer.Write(stamp ?? "");
}
var protectedBytes = Protector.Protect(ms.ToArray());
return Convert.ToBase64String(protectedBytes);
So the basic calculation for length of the memory stream would be:
27 characters for DateTimeOffset.UtcNow
36 characters for the user id (string representation of a GUID)
20 characters for my specific "purpose" string
36 characters for the security stamp (string representation of a GUID)
---- +
119 characters in total
In the code snippet this gets Protected and then converted ToBase64String
When I casually tested this on my local machine, I got an encrypted string of 352 characters. How could I predict that the 119 input characters would become 352 characters when encrypted? And worse, my app runs actually in production on an Azure App Service where Azure's DPAPI should kick in, possibly with different encryption than on localhost?
Can I in any way predict what the maximum length of the generated User Tokens will be on Azure App Services? I'm happy to include a margin of error, but am clueless what that would need to be.
By default DPAPI uses AES-256-CBC as encryption algorithm unless you change it via UseCryptographicAlgorithms. As per default algo, the calculation would go like this for your case:
Since it's AES 256, it would work with 32 bytes block. So with CBC padding, you output becomes ((119/32) + 1) * 32 + 16 (IV) = 144. After base64, it becomes 192.
So, having it 352 brings up the question is the stamp really 36 in your case?
36 characters for the security stamp (string representation of a GUID)
Also, in deployed environment, make sure to store data protection key outside app since each instance of the app service needs to point to the same key.

parsing base64 blob from tool output

I have a problem parsing base64 encoded blob from tool output.
I'm using this regex in c#: #"(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)"
Everything worked fine until the blob I receive looks like following (it does not have even one '='. according to wiki base64 string can have 0-2 "=" signs in the end/)
I cannot work with string before and after the blob because it can be muli-language
Provisioning the computer account... Successfully provisioned
[user-1009-1-] in the domain [testauto.sof]. Provisioning data was
saved successfully to
[C:\Users\user1\AppData\Local\Temp\user-1009-1-.blob]. Provisioning
string (2624l bytes):
ARAIAMzMzMzIAwAAAAAAAAAAAgABAAAAAQAAAAQAAgABAAAAAQAAAKADAAAIAAIAoAMAAAEQCADMzMzMkAMAAAAAAAAAAAIABAACAAgAAgAMAAIAFAAWABAAAgAcAB4AFAACABwAHgAYAAIA5pXFb5WfaEeEDMNZ4eUJVxwAAgAgAAIAJAACAAEAAADmlcVvlZ9oR4QMw1nh5QlXKAACACwAAgD8MQDgMAACADQAAgACAAAADwAAAAAAAAAPAAAAbQBpAHIAYQBnAGUAYQB1AHQAbwAuAHMAbwBmAAAAAAAQAAAAAAAAABAAAAB4AGkAcwBoAGUAbgBnAC0AMQAwADAAOQAtADEALQAAAHkAAAAAAAAAeQAAAF0APwAjAHkAWgBYADoAdwBgAGUANgB2AG8AJQBuAHkAIwBUAE4ALAAxAHUAOQBkAD4AdwA5AG8AaABgAHEAIwBhADYALABwAF0ALwBoAEgAIABqAHMATwA5AGwATgB5ADEAVQAhAE4ASwAiAEUAPQA8AGIAZQBAAC8ARgA1AGIAQAAiAG8AUgA6AGIAawAzAF4AVwBrACYATQA5AE8AdQBvAHYAZQA0AGMAKwBDAHMAUABrAGsAdQBAAF4AYAAgAFsAJQBgAGUAJwAuAG8AOwBBACgATQBuACIARgAlAG0ASwA1ADMAbQBJAHcAXQBkAAAAAAALAAAAAAAAAAoAAABNAEkAUgBBAEcARQBBAFUAVABPAA8AAAAAAAAADgAAAG0AaQByAGEAZwBlAGEAdQB0AG8ALgBzAG8AZgAPAAAAAAAAAA4AAABtAGkAcgBhAGcAZQBhAHUAdABvAC4AcwBvAGYABAAAAAEEAAAAAAAFFQAAAN0GKLrAxnxUyKGAThoAAAAAAAAAGgAAAFwAXABTAE8ARgAtAFEAQQAwADIALgBtAGkAcgBhAGcAZQBhAHUAdABvAC4AcwBvAGYAAAANAAAAAAAAAA0AAABcAFwAMQAwAC4AMgAzAC4ANwAyAC4AMgAAAAAADwAAAAAAAAAPAAAAbQBpAHIAYQBnAGUAYQB1AHQAbwAuAHMAbwBmAAAAAAAPAAAAAAAAAA8AAABtAGkAcgBhAGcAZQBhAHUAdABvAC4AcwBvAGYAAAAAABgAAAAAAAAAGAAAAEQAZQBmAGEAdQBsAHQALQBGAGkAcgBzAHQALQBTAGkAdABlAC0ATgBhAG0AZQAAABgAAAAAAAAAGAAAAEQAZQBmAGEAdQBsAHQALQBGAGkAcgBzAHQALQBTAGkAdABlAC0ATgBhAG0AZQAAAAAAAAAAAAAA
Computer account provisioning completed successfully. The operation
completed successfully.
Anyone can help me to fix the regex?
Here is regex calculator that I using:
http://regex101.com/r/wP3kP9/1
The following should work successfully:
^(?!$)(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)?$
regex101
In my understanding, if no = is present, it's because the string length is a multiple of 4.
I also anchored it with ^...$and used the m option so only your base64 string matches. I added (?!$) so empty lines don't match (couldn't simply change the * to + because you may want to match short strings like aa==).

C# Comport - Possible Loss of Data

I have been trying to troubleshoot an issue and I really don't have any thoughts as to go about resolving the following problem:
I have a software application that is able to listen for a device that is capable of uploading data to a computer. Once this data is captured, it is written to a text file and stored for later use.
void DataRecieved(object sender, EventArgs e)
{
while ((bufferedData = comport.ReadLine()) != null)
{
uploadedData += bufferedData + Environment.NewLine;
}
comport.Close();
System.IO.StreamWriter writeUploadedPro = new System.IO.StreamWriter(uploadFilePath);
writeUploadedPro.Write(uploadedData);
writeUploadedPro.Close();
isUploadComplete = true;
}
I can establish, recieve, and verify a connection, and what I have programmed does indeed produce a text file of the uploaded data, however the data is contains is not complete.
Example:
%
N0?77??.5???3
G0? X3.??? Z4.5??6
Z5.??
?3.5?76
G01 Z5.??
Z4.9471
X?.?3 Z4.???9
Z?.???6
?3.?? Z?.???
Z4.????
X3.7??4
G?? X3.???? ?4.5??6
M30
?
It has numerous '?' which either should be a letter or digit. I have reaffirmed that the settings I have for the comport (Baud, Data, Stop, Parity, Handshake, and COM name are correctly specified). I have also tried setting the ReadBufferSize, RecievedBytesThreshold, Encoding, and NewLine settings. I am not at all familiar with these properties and I didn't find MSDN to be to helpful on explaining them either.
If you have any ideas or suggestions as to why I am getting incomplete lines of data in my upload, it would be most appreciated. Thank you for your assistance.
The problem is in your encoding. Try changing the Encoding property to UTF8. The default is ASCII. In ASCII encoding, any character greater than 0x7F gets converted into a ? by default because ASCII only goes up to 0x7F (127 decimal).
Though that might fix your problem, the better way to go would be to read the data into a byte array, then use one of these encoding classes to convert it into a proper string. The reason why that works is because you no longer converting the received bytes into a string. You're using the Read(byte[], int, int) overload which doesn't do a string conversion. Its pure bytes.
I think the problem lies in:
while ((bufferedData = comport.ReadLine()) != null)
Try changing the statement to something like:
while(comport.BytesToRead>0)
{
uploadedData += comport.ReadExisting() + Environment.NewLine;
}
Let me know if that helped.

How can I generate a .pfx file?

Is there any way to create .pfx files in order to sign documents,
I've found a program called x509 Certificate Generate,but I want to know if it can be generated in code using c#.
There is a Microsoft command-line tool makecert that can be used to generate certificates. It's part of the Windows SDK. On my machine there are half a dozen versions e.g. in C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64. Then in your code you can start a process to run the executable with the appropriate parameters.
You could check out the Bouncy Castle API, it can be used to generate certificates using C#.
First of all, signing documents with self-signed certificates makes no sense unless you have custom PKI hierarchy in your organization (and in the latter case you need to know well what you are doing, which seems to be not the case).
PFX is a container for one or more certificates with associated private keys. So you don't generate "PFX file". You generate a keypair and create a certificate, which can then be exported to PFX file or to other format.
As mentioned above, BouncyCastle can generate certificates, and our SecureBlackbox library also can generate certificates and save and load them to/from many different formats.
If you read about makecert like #David Clarke's answer refers to, you will see to fulfill your requirement, you just need a managed makecert written in .NET.
Luckily the Mono guys have implemented this a long time ago,
https://github.com/mono/mono/blob/master/mcs/tools/security/makecert.cs
You can make digital signature by using adobe reader
if you are using adobe x
-then go to 3rd option from left
-here you can see signing setting
-open this and go to add id
-just enter your details and your are done .pfx file is ready where ever you browsed it....
-it is valid for 6 years
You can use OpenSSL.NET library for this.
Here is the code example how to do it:
public X509Certificate2 GeneratePfxCertificate(string certificatePath, string privateKeyPath,
string certificatePfxPath, string rootCertificatePath, string pkcs12Password)
{
string keyFileContent = File.ReadAllText(privateKeyPath);
string certFileContent = File.ReadAllText(certificatePath);
string rootCertFileContent = File.ReadAllText(rootCertificatePath);
var certBio = new BIO(certFileContent);
var rootCertBio = new BIO(rootCertFileContent);
CryptoKey cryptoKey = CryptoKey.FromPrivateKey(keyFileContent, string.Empty);
var certificate = new OpenSSL.X509.X509Certificate(certBio);
var rootCertificate = new OpenSSL.X509.X509Certificate(rootCertBio);
using (var certChain = new Stack<OpenSSL.X509.X509Certificate> { rootCertificate })
using (var p12 = new PKCS12(pkcs12Password, cryptoKey, certificate, certChain))
using (var pfxBio = BIO.MemoryBuffer())
{
p12.Write(pfxBio);
var pfxFileByteArrayContent =
pfxBio.ReadBytes((int)pfxBio.BytesPending).Array;
File.WriteAllBytes(certificatePfxPath, pfxFileByteArrayContent);
}
return new X509Certificate2(certificatePfxPath, pkcs12Password);
}

Categories

Resources