I am trying to implement HTTP communication authenticated by client certificate. When sending an HTTP request on "normal" (i.e. not Compact) .NET Framework, it's quite simple:
HttpWebRequest request = ...;
string certificatePath = ...;
string certificatePassword = ...;
request.ClientCertificates.Add(
new X509Certificate(certificatePath, certificatePassword));
However, on Compact Framework 3.5, X509Certificate has only one constructor which accepts byte array and nothing else. I suppose that I should read a certificate file and pass its contents into that byte array, but what about the password? How should I specify it on Compact Framework?
I did not find any way to use X509Certificate and password.
In the end, I've decided to use X509Store and grab certificates from there. This will make deployment a bit more difficult then originally anticipated, but at least it's doable :)
I'm two years late, but I stumbled across this question in my own research.
If you look closely at the documentation's example code, you see that you have to first open the PFX file and then export it before creating another instance of the X509Certificate class.
The way I understood this is as follows: the full .NET Framework API (i.e., on the desktop) takes a password parameter for the class' constructor as an overload. So, using the full framework, you export the certificate's raw data (i.e., without the securing password) using the Export method and then store the resulting byte array into a file. Afterward, you transfer that file to the mobile device, read the file into a byte array and pass that to the X509Certificate constructor on the Compact Framework.
Of course, this is the "raw" way of going about the problem. One has to then take care to secure the data being transferred in some way.
On further reading, exporting the PFX file in this way does not include the private key, though.
Related
I'm trying to add a certificate to my HTTP Client (my HTTP request really) but I'm not quite sure what I'm doing.
I have three files:
key.pem
cert.pem
cacert.pem
I'm aware that the cacert.pem file does not require a key since it's just the public part, so I'm not looking for a key for that or trying to use my key.pem.
So what is it I'm exactly supposed to do? My endgoal is to simply have a request like
curl -k http://example.com -v -key c:\path\key.pem -cacert c:\path\cacert.pem -cert c:\path\cert.pem
from my HttpClient.
I know HTTP Client uses a collection of X509Certificate2 which can be extracted from a .pem file (and a key.pem file), but it doesn't look like it can be built from two. I also know there's a X509Chain which seems like something that could be useful but it also seems significantly more customizable than a simple "combine two certficats" tool would be.
I should mention that I am in no way versed in certificates or anything crypto, I'm a simple grease monkey mostly qualified in business logic, so please assume nothing except that I know very little on the subject and the tools needed for it.
UPD: One limitation I forgot to mention: I am using .NET Core 3.1 with no way to upgrade to .NET 5. Legacy code and all that.
I am fetching my organization's applications using the MS Graph API, and I am attempting to read the thumbprints of the certificates attached to each. It returns a byte[] but I can't seem to find the right encoding to convert to string.
The graph API returns a list of Application objects, which have a KeyCredentials enumerable, and finally a CustomKeyIdentifier, which should be the thumbprint. See this Microsoft page for more details on KeyCredentials.
The code I have tried is
System.Text.Encoding.ASCII.GetString(credential.CustomKeyIdentifier);
This returns gibberish characters, presumably because the encoding is incorrect, but I have tried every other encoding option available in Text.Encoding to no avail. How can I convert the CustomKeyIdentifier to a string?
It should be a Base64 string so
System.Convert.ToBase64String(credential.CustomKeyIdentifier);
Or if you want the Hex version which is generally what people want when looking at the thumbprint it would be
BitConverter.ToString(credential.CustomKeyIdentifier).Replace("-","");
I am trying to consume a Java web service from a C# client. The service requires BinarySecurityToken element with value type X509PKIPathv1.
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1">
MIIH......
</wsse:BinarySecurityToken>
Since WCF does not support X509PKIPathv1 value type, I am generating the SOAP message by hand, signing it using the SignedXml class, encrypting it using the EncryptedXml and sending it using the WebClient class. As for the value of BinarySecurityToken element, I used the value generated in SoapUI for the same certificate, and it works.
But, I would like to be able to generate this value programmatically from .p12 file, and not having to paste it from SoapUI again every time when the certificate expires.
The WS-Security documentation is a bit vague, so I am not sure how to go about it. This is all the information it gives about this token type:
#X509PKIPathv1: An ordered list of X.509 certificates packaged in a PKIPath
How to generate this value from .p12 file in C#? SoapUI does it somehow.
So this may not be a fully solution to your problem but it may help you out somewhat.
This:
#X509PKIPathv1: An ordered list of X.509 certificates packaged in a PKIPath
means is a asn1 sequence or chain of certificates that you have used to sign your message. You can even see it here.
To give some context asn1 is way of representing data in way independent of the machine you are using. This data is binary and not human readable so you transform it to bade 64 and that is what you see in that field.
I am not entirely sure what the exact content of your .p12 file is but at the very least I assume it has the certificate of the private key you used to sign your message and maybe the chain until the publicly trusted certificate or CA.
I am mostly a C++ developer and I know openssl provides a C like api to read a certificate manipulate the underlying asn1 structure and the output it as a string.
Sorry for not providing with a greater level of detail or a code example
I have a scenario where users are Uploading Transactions logs to Main Server Via ASMX Webservice. The application is clickonce .Net winforms app
Currently I am doing this To convert to List of Object to Json and Deserialize it on Service. over the SSL.
string data = JsonConvert.SerializeObject(Values_Static.logitems);
My Code is protected by SmartAssembly . And still I am getting some breach that attacker have access to the Network Connections and Can Deserliaze the Data.
Now i am thinking of a Scenario that I Encrypt the Json String with some private string key and then decypt it on the server .
e.g
private string salt = "$e7?8f#l4";
return ByteArrToString(Encrypt(TextValue + salt));
Hardcode the key in app and decode it in server.
will it work ?
Users are uploading the the logs to server every minute and there are possibly 20-30 entries per Upload.
is there any chances of broken Data or still the hacking ?
UPDATE :
According to Discussion Below . I understand that there is some issue with my Code. The code is accepting the invalid certificate . How i Can prevent to Accept only Valid Certificate from my https:// Web service .
ATM , every one can see the code through fiddler with Decryption HTTPS on .
I have a valid Certificate installed on my IIS 7. and its working properly
the issue is with code. and its standard auto generated web reference in Visual Studio.
UPDATE 2 :
The Final Result is , The Post data is not Encrypting , its Plain XML and readable by any software that can sniff , however the GET data is secure . I had serached bit not found some valid Answer.
Are you using SSL? If so, any application-level encryption is redundant. And, the key will have to be embedded in the code, so is readable by any attacker.
Fiddler (or other HTTPS proxies) can decrypt any HTTPS traffic.
You could prevent simple use of Fiddler by requiring a specific server certificate in your client code (rather than trusting any certificate the system itself trusts). However, this is only a weak deterrent because the user could just decompile your code and alter it so that your new certificate check is neutered.
This is called the "Untrusted client" problem, and it's the same thing that makes Digital Rights Management (DRM) software a "best effort" affair rather than an ironclad protection.
Ok, I've never seen this ever when coding againts and sending 3rd party SOAP API calls but looks like PayPal requires their bigger clients to use the X509 certificate in order to send API calls rather than just sending over a standard API signature like most APIs require you to do.
Am I the only one who thinks this is kinda strange or not stadnard?
http://en.wikipedia.org/wiki/X.509
I don't get how this relates to an API call. I see an example code that they gave me in C# implementing the ICertificatePolicy interface in .NET...but it's just foreign to me and how this relates to the fact that they still give you an API signature too in the PayPal sandbox regardless. So why would I need to read a physical file Certificate AND use an API Signature? I guess I don't see the link between the Certificate and the PayPal SOAP API.
This is a common thing among larger names when dealing with connections that demand a more secure "handshake" and thats all it is used for.
This file is made from a Root Certificate and usually a .pem, .p12, .pfx here is an example using python and cURL, it is very simple to do and if you have any trouble with the X.509 file, I would get in contact with whoever you buy your root certificate from or just search google on how to export the file you need ( I personally always end up with a .p12 file ).
Here is the python code
c = pycurl.Curl()
c.setopt(pycurl.URL, FirstDataAPI_URL)
c.setopt(pycurl.HTTPHEADER, ["Accept:"])
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, urllib.urlencode(FirstDataAPI_PostData))
b = StringIO.StringIO()
c.setopt(pycurl.WRITEFUNCTION, b.write)
c.setopt(pycurl.FOLLOWLOCATION, 1)
c.setopt(pycurl.MAXREDIRS, 5)
#c.setopt(pycurl.SSLCERT, '/home/***/***/***/ssl/digitalID.p12')
c.setopt(pycurl.SSLCERT, '/home/***/***/***/ssl/productionDigitalId.p12')
c.setopt(pycurl.SSLCERTTYPE, 'p12')
c.setopt(pycurl.SSLCERTPASSWD, '******')
c.perform()
For use with SOAP I would look for a setting that allows you to set a Certificate file and you will be set.
Just as a side note, this just goes to show that Paypal has not updated their API in quite a few years ... most API's I work on that require a X509 cert are extremely outdated and I haven't seen this used in an API that was writing in the last 2 years.
You're dealing with people's money, and while I'm unaware of the specifics on how the certificate's work, basically it's ensuring that payments sent from your application are more secure.
A simple API key would be easier to spoof, and allow fraud more easily I assume.