How get X509 certificate's full cert chain programatically? - certificate

Imagine I have p12 container of private key and public certificate. When I export p12 public cert to separate .cer file with Java keytool I may click to .cer file and see full cert chain. How may I get that full path programatically?
I made little investigation. I used keytool's print cert -v command and saw property AuthorityInfoAccess with subproperty
accessMethod: caIssuers
accessLocation: URIName: http://.../some.crt
I downloaded that some.crt (it was PEM cert), and again used print cert -v and again saw
accessLocation: URIName: http://.../some2.crt and repeated downloading .crt files and geting parent until reaching root .crt which hasn't such property.
I think, that I should programatically download chain as I described above and provide it to CertPathValidator as shown here.
If I really need to get chain as I described above, is there any libraries already doing this? Is there any way to do it with std lib? I didn't find bouncycastle examples and java's standart library code like
java.security.cert.Certificate[] cchain = keystore.getCertificateChain(alias);
returns one entry for certificate actually having 2 "parents".

Nitpick: you surely mean keytool -printcert (with hyphen, without space, -v not needed here).
A privatekey entry created by Java in JKS or PKCS12 usually contains the full chain, but keytool -exportcert extracts only the leaf cert.
A PKCS12 created by something else may contain the full chain or not, possibly depending on what you clicked when creating it.
If the chain is there, KeyStore.getCertificateChain returns it, and keytool -list -v (here -v matters) shows it.
If a certificate was imported, or reimported, as a trustedcert entry -- usually in JKS, PKCS12 isn't designed for lone certs -- that never contains the chain, so getCertificateChain on that entry won't work, but IIRC CertPathBuilder can build a chain combining multiple trustedcert entries in one store.
If you do need a parent (chain) cert
you don't already have, and the child specifies AIA.caIssuers, then yes using that to fetch is sensible.
I'm pretty sure there is nothing in standard Java (JRE) library that does this for you, at least so far; I don't know about BouncyCastle or anybody else.

Related

CouchDB SSL CRT to PEM files

I have tried several ways to get some PEM files to be used by CouchDB. I have generated a cert with powershell, exported it with key to a pfx and then used openssl to convert to 2 pem files and installed them in Couch. With this approach it seems to work in IE11, but it doesn't work with firefox or other browsers. Firefox produces this error:
The key does not support the requested operation. (Error code:
sec_error_invalid_key)
I've also gotten a free ssl cert from ssl.com, (they gave me three CRT files) and tried converting it using openssl, but to no avail.
I've also followed the instructions on the page from CouchDB to generate a self signed cert specifically for this purpose, but it will not load the page. (http://docs.couchdb.com/en/latest/config/http.html#config-ssl about half way down)
Has anybody had success with this? How do I get my certs into a format that will play nice with Couch and will all browsers?
UPDATE:
Now I'm getting this error
A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.
Not sure if this is a step forward or backwards...
It seems like CouchDB versions predating 1.7 or 1.6 are not able to have intermediate certificates specified for certificate verification. Since you are writing about having received three .crt files, (s)ome of those might be required as intermediate certificate(s). CouchDB not knowing about them can be the cause of your problem.
Apparently, one way to work around this is to concatenate your certificate file along with the intermediate certificate file(s). Simply cat them together like
$ cat yours.crt theirs.crt > couchdb.crt
...and use CouchDB's certfile configuration option to point to couchdb.crt's location.
If you prefer to convert .crt to .pem first, use sth like
$ openssl openssl x509 -in yours.crt -inform der -outform pem -out yours.pem
In a new enough version, you can probably use an intermediate certificate by setting CouchDB's cacertfile option. Have a look at this for further information.

About Getting Started with the Facebook SDK for Unity

I am trying the new Facebook SDK for Unity and I would like to deploy the example included in this SDK but like I am not running any web server. I installed the Python software in the default path (C:\Python33) and the I created web.py file and saved it into the built my Unity game (where is web.unity3d file). More info here.
See I don't have a web server available part.
Since my English is not so good, I could not understand the following part:
Then (install openssl)[http://www.openssl.org/related/binaries.html]
if it isn't already on your computer. In the same directory as above,
generate a key file:
openssl req -new -x509 -keyout server.pem -out server.pem -days 365
-nodes Provide a non-blank answer to each prompt (correctness won't matter, but empty values may).
Start the server:
python web.py
For this, could anybody explain to me how I would have to do it?
Facebook is providing instructions on how to deploy a simple web server locally if you don't already have one, specifically the SimpleHTTPServer one (http://docs.python.org/2/library/simplehttpserver.html). The prerequisite is to have a SSL/TLS-capable Web server. So
First Step: Allow for SSL capability by using openssl to generate a key file for use in the server. (Keep it in the same directory)
openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -node
After executing this command, a series of prompts will be asked but for the purposes of the tutorial it isn't important what the values are as long as they are non-blank
Second Step: Create a file called web.py with the following contents
import BaseHTTPServer, SimpleHTTPServer
import ssl
httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='server.pem', server_side=True)
httpd.serve_forever()
This line
httpd = BaseHTTPServer.HTTPServer(('localhost', 4443), SimpleHTTPServer.SimpleHTTPRequestHandler),
is how the server will be presented in a browser, https://localhost:44443/, where the game object will be at https://localhost:44443/web.unity3d
This line
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='server.pem', server_side=True)
sets up SSL with the server key file generated earlier with openssl
Finally httpd.serve_forever() executes the requests and deploys the server at https://localhost:44443/
Third Step: Call the program just created by executing the following command
python web.py
Fourth Step: Navigate to https://localhost:44443/web.unity3d
Alejandro - you don't actually need to set up a localhost server, in fact, I don't recommend it unless you really want to iterate on some Facebook callbacks and you're having trouble getting them working.
Instead I would:
do in-editor testing just to see how things might work. The editor dialogs use fake data, but are indicative of the in-game experience.
push to a hosting site for live testing. e.g. use parse hosting and do 'parse deploy' to push a static file live. I can help with this if you'd like.
Thanks for checking out the SDK!
you are installing the wrong python version. Use 2.7, not 3.3. 3.3 doesn't have that library.

Profiles installed by MDM service are showing as "Not Verified" after upgrading the device to iOS 6

Profiles installed by MDM service are showing as "Not Verified" after upgrading the device to iOS 6. These profiles were signed by a InCommon cert issued by AddTrust before being pushed to the devices. They were showing as "Verified" before the upgrade. Any ideas what might have caused this?
I got exactly the same problem so it is probably a bug in the iOS profile system because the very same SSL certificate is trusted by the browser. Note: Our certificate is of the "*.host.org" type.
This might be an untrusted CA in the certificate chain from the cert provider you bought it from. Looks like some CAs are untrusted or missing from iOS6. I had the same problem and included the whole of the cert chain in our cert signing bundle and the issue was resolved.
Suggest you open a support case with your cert provider to see if it's a known issue or dig around to see if you can find a list of trusted CAs used in iOS6 - I couldn't find one. Synching the device to iTunes may also refresh the CA list but this didn't work for me this time.
I have exactly the same problem as your.
My chain is GeoTrust -> RapidSSL -> MyCert. I have included the full chain in my .crt, but it stills show "not verified" when I try to install the configuration profil.
I don't know how to insert the whole path.
I use an openssl command to sign my file :
openssl smime -sign -signer #{crt_path} -inkey #{private_key_path} -nodetach -outform der -in #{file_to_sign_path} -out #{file_signed_path}
My crt_path is a .crt file, including the three certs.
EDIT
I found out the problem with my openssl command. My full chain was in the #{crt_path} but was not used by the command. I added the *-certfile #{crt_path}* and things works well !
Including the intermediate cert in the pkcs7_sign call (php openssl_pkcs7_sign() in my case) revolved the problem.
Yes! Adding the entire path (-root) did the trick.
Verify that the signature created by the MDM SW actually contains the path. Since it wasn't needed before...

Apple Push Notifications, how do I properly export my cert?

I can't seem to figure out how to properly export my cert for use in my iOS app with push notifications. I'm using the following cert, downloaded from the Certificates section of the iOS Provisioning Portal.
I'm then following one of the many tutorials I've found all over the web that are all different by the way, to get my cert into a .pem format for use in ruby-apns.
First I export it from the Keychain:
After I give it a name and a password I perform the following commands in the terminal*:
openssl pkcs12 -in cert.p12 -out apple_push_notification_dev.pem -nodes -clcerts
*note: this isn't the only way I've tried this, just the latest, I have also tried via the instructions at the following urls:
http://blog.boxedice.com/2010/06/05/how-to-renew-your-apple-push-notification-push-ssl-certificate/
http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/
http://code.google.com/p/apns-sharp/wiki/HowToCreatePKCS12Certificate
http://wiki.cs.unh.edu/wiki/index.php/Using_the_Apple_Push_Notification_Service
Not a single one of these solutions work. I'm sitting here looking at the following error from the console when I try to use ruby-apns:
read finished A: sslv3 alert certificate unknown (OpenSSL::SSL::SSLError)
And essentially every other server solution I've found has told me my certificate is incorrect or that there's a problem with it as well.
Am I doing this wrong?
===============================
Overnight Courtesy Bump Stealth Edit
So I beat my head against the wall last night, and actually came across Apple's own instructions for doing this. It's almost the exact same, and I tried it to the same tune. Nevertheless, here is the latest attempt from this link:
openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes
(1) First you need to set the configuration for your app ID to enable push notification service. You can check in the image.
(2) Then You can install the certificate and intall in your keychain in your machine.
(3) Here you are exporting two files. Instead of that you just need to export the private key as shown in the screenshot.
(4) Now you can export the private key and store with any name you want in .p12 format as shown in the screenshot below.
(5) Then follows all other steps as you know very well like you mentioned above.
openssl pkcs12 -in CertificateName.p12 -out CertificateName.pem -nodes
Please let me know if you still have any question or if you are not able to solve then let me know.

Push Notification Error: "Unable to set local cert chain file"

I wrote a test php page that just sends out a generic push notification and it works intermittently. Sometimes it delivers the message and other times I get this error:
"Message: stream_socket_client() [function.stream-socket-client]: Unable to set local cert chain file `/var/www/ninerobot.com/public/mlb/certs/mlbtr-push-dev.pem'; Check that your cafile/capath settings include details of your certificate and its issuer"
Do you know how I can solve this issue?
I see that on Apple's docs it says "Note: To establish a TLS session with APNs, an Entrust Secure CA root certificate must be installed on the provider’s server. If the server is running Mac OS X, this root certificate is already in the keychain. On other systems, the certificate might not be available. You can download this certificate from the Entrust SSL Certificates website." Does this mean anything that I need to do?
Me too got more struggle to do the same. Eventually I found solution to send push notification through PHP global url. Try the below steps. Before that I hope you all know to generate the 3 certificates thats PushChat.certSigningRequest, pushkey.p12 & aps_development.cer (csr,p12,cer)
Open your Terminal and step by step run the below commands:
# Make sure terminal refers your correct certificate path.
$ cd ~/Desktop/
# Ask system administrator to open if its not connected
$ telnet gateway.sandbox.push.apple.com 2195
Trying 17.110.227.35...
Connected to gateway.sandbox.push-apple.com.akadns.net.
Escape character is '^]'.
# Convert .cer to .pem
$ openssl x509 -in aps_development.cer -inform der -out PushCert.pem
# Convert .p12 to .pem. Enter your pass pharse which is the same pwd that you have given while creating the .p12 certificate. PEM pass phrase also same as .p12 cert.
$ openssl pkcs12 -nocerts -out PushKey1.pem -in pushkey.p12
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
# To remove passpharse for the key to access globally. This only solved my stream_socket_client() & certificate capath warnings.
$ openssl rsa -in PushKey1.pem -out PushKey1_Rmv.pem
Enter pass phrase for PushChatKey1.pem:
writing RSA key
# To join the two .pem file into one file:
$ cat PushCert.pem PushKey1_Rmv.pem > ApnsDev.pem
Then Finally move the SimplePush.php to the ApnsDev.pem file location. Both files will be in same folder. and change Device Token, Pass Phrase, Certificate Name(ApnsDev.pem), Message… In simplepush.php Download the file using the below URL.
http://d1xzuxjlafny7l.cloudfront.net/downloads/SimplePush.zip
Then execute the file in terminal or your domain server
$ php simplepush.php
or
www.Domainname.com/push/simplepush.php // Now, url shows 'Connected to APNS Message successfully delivered'.
Thats it, the push notification will fly and reach the specific IOS device.
If you want to send 'Badge' then change the payload code in simplepush.php like below,
// Construct the notification payload body:
$badge = 1;
$sound = 'default';
$body = array();
$body['aps'] = array('alert' => $message);
if ($badge)
$body['aps']['badge'] = $badge;
if ($sound)
$body['aps']['sound'] = $sound;
// End of Configurable
// Encode the payload as JSON:
$payload = json_encode($body);
Now run the php file again and the app icon appears with badge number in red circle.
Use this checklist to work through this:
Did you create a legitimate certificate via instructions like these.
Is your .pem file readable by your webserver process (ie permissions and file location are good)? Many setups run apache, for example, under the "www-data" user/group. Side note: make sure visitors can't view the .pem file by browsing to it.
Does your server have the Entrust Secure CA Root Certificate (2048 bit) installed? If not, follow instructions for downloading/installing for your particular server OS.
Is outbound TCP port 2195 open? Many hosting providers do NOT have this outbound port open by default.
In addition to a great answer of Steve N let me add the last point.
Ensure you understand the warning, especially include details of your certificate and its issuer. You probably don't have a block in your .pem file, i.e. issuer= , subject= etc. and your file begins with -----BEGIN CERTIFICATE. It can be accidentally deleted during conversion of the certificate file.
Might be irrelevant for OP's Q, but I've tried all openssl statements with all the different flags, while trying to connect with PHP \SoapClient(...) and after 3 days I finally found a solution that worked for me. Posting so the next dude(tte) may find this easier than me.
GitBash
$ cd path/to/certificate/
$ openssl pkcs12 -in personal_certificate.pfx -out public_key.pem -clcerts
First you have to enter YOUR_CERT_PASSWORD once, then DIFFERENT_PASSWORD! twice. The latter will possibly be available to everyone with access to code.
PHP
<?php
$wsdlUrl = "https://example.com/service.svc?singlewsdl";
$publicKey = "rel/path/to/certificate/public_key.pem";
$password = "DIFFERENT_PASSWORD!";
$params = [
'local_cert' => $publicKey,
'passphrase' => $password,
'trace' => 1,
'exceptions' => 0
];
$soapClient = new \SoapClient($wsdlUrl, $params);
var_dump($soapClient->__getFunctions());