FOSS Fridays: OpenSSL in PHP

Well Twitter has “Follow Fridays” so I thought we should do FOSS Fridays. I don’t really have a plan for this and it might not last but let’s see where it goes.

In the last few days a couple of people have asked for tips on how to use OpenSSL from PHP. So here is a snippet on how to do it. This comes out of an application that provides a shared authentication system between our client’s LDAP system and their partner’s systems.

It works like so:

  1. Users login to the application using their LDAP credentials.
  2. When the users request to visit the partner site, our system packages up their login information, encrypts it, signs it, and shoots it along with the user to the partner site.
  3. Next, the partner checks if the user has an account and if they do it logs them in. Otherwise, it creates them a new account and logs them in.

All of this is done transparently so that the user doesn’t know they’ve actually left the original site.

Here is the code to do it. PS. it’s from a Symfony application.

<?php
$user = $this->getUser();

$profile = $user->getProfile();

if(is_null($profile)){ die("Could not get user profile?"); }

$email = $profile->getEmail();

$firstName = $profile->getFirstName();

$lastName = $profile->getLastName();

$password = $request->getParameter("password");

$keyText = file_get_contents(sfConfig::get("sf_root_dir") . "/" . sfConfig::get("app_their_public_key"));

$theirPublicKey = openssl_pkey_get_public($keyText);

$keyText = file_get_contents(sfConfig::get("sf_root_dir") . "/" . sfConfig::get("app_our_private_key"));

$outPrivateKey = openssl_pkey_get_private($keyText);

$arr = array();

$arr["U_EMAIL"] = $email;

$arr["U_PASSWORD"] = $password;

$arr["U_FIRST_NAME"] = $firstName;

$arr["U_LAST_NAME"] = $lastName;

$arr["RL_E"] = $this->generateUrl("ps_error", array(), true);

$arr["RL_S"] = "PRIVATE URL";

$arr["ETIME"] = time() + 60;

$queryString = http_build_query($arr);

$res = openssl_sign($queryString, $signature, $outPrivateKey);

if(!$res){ throw new sfException("Could not sign the payload!", 1); }

$t = openssl_pkey_get_details($theirPublicKey);

$t = (int) ($t['bits'] / 8 ) - 11;

$l=strlen($queryString);

$cryptPayload = '';

for ($i=0; $i<$l; $i+= $t) {

  $block = substr($queryString, $i, $t);

  if (!openssl_public_encrypt($block,$tS, $theirPublicKey)){
    throw new sfException('failed encrypt', 1);
   }

  $cryptPayload .= $tS;
}

$this->encodedSignature = base64_encode($signature);

$this->encodedData = base64_encode($cryptPayload);

The net result of all of this is an encrypted payload with the user’s credentials and a signature of the payload. The payload is encrypted with “their” public key and then signed with “our” private key. This ensures that only they can open the package and only we can generate valid signatures.

Happy Friday!

Google Calendar API create on alternate calendar

A few months ago we integrated Google calendar into an application that we built for a client. Anyway, today I sat down to customize which calendars certain events were being created on. We’re using the Zend Framework’s GData package to interact with Google Calendar and surprisingly the documentation is pretty lacking.

Specifically, I was looking to create events on a calendar that was not the “primary” calendar for a user. After poking around and experimenting, I finally got things to work.

First, you can retrieve the list of available calendars with:

<?php
$service = Zend_Gdata_Calendar::AUTH_SERVICE_NAME;
$user = sfConfig::get("app_gcal_user");
$pass = sfConfig::get("app_gcal_password");

$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
self::$service = new Zend_Gdata_Calendar($client);
$calFeed = self::$service->getCalendarListFeed();

$arr = array();
foreach ($calFeed as $calendar) {
  $arr[] = array( “title” => $calendar->title->text, “uri” => $calendar->getEditLink(“alternate")->href   );
}

Next, when creating the events pass in the uri and the events will appear on the alternate calendar.

self::$service->insertEvent($event, $arr[1][“uri”]);

99designs and Amazon. Design. Crowd sourced.

A week or so ago my Dad asked if we could have our designer put together a logo for him. Unfortunately, our guy was buried under a mound of work and generally couldn’t help us out. We haven’t always had the best luck with Craigslist so I was ready to try something new.

Over the last few months, I’ve been seeing a good amount of chatter surrounding “spec” design sites especially 99designs.com. After taking a look around the site I figured now was a good time to give it a shot. We were on a tight budget, tight time line, and my Dad didn’t have much direction for the logo.

I posted up a contest last Sunday here and we were looking at entries by Monday afternoon. Now things got more difficult. We were having a hard time coming up with “star ratings” and constructive feedback in general. My Dad’s staff was having a hard time not getting pigeon holed by the submitted designs and Setfive wasn’t doing a great job helping them along.

We did our best and we felt like the entries were moving in the right direction. Then the contest closed. In the last 8 hours of the contest the number of entries nearly doubled. With 70 entries we now had the problem with objectively picking a winning logo.

At this point, I wanted some more input on what people thought about the logos. I decided to create a set of Amazon Mechanical Turk tasks to get some feedback.

After about a day, I had 200 responses asking for user’s top three logos and any additional comments they had.

Some of the comments I got back were insightful and moving:

  • Don’t pick any of the logos on the second page. They all look terrible.
  • Due to nature of your business I would prefer a sober and serious looking logo.
  • I chose these three because they are visually appealing, and convey a sense of being able to ease pain.
  • I suffer from cronic pain. I wish you the best of luck in finding your logo. People that do your type of work are a life line for people like me. Hope I hope have helped.

I tallied up the results by weighting +3, +2, +1 for first, second, and third choices respectively. The results were interesting.

  • Every logo received at least one vote.
  • The top ten logos accounted for just about 41% of all the votes.
  • Only counting the top choice caused 3 logos to fall out of the top ten.

The top ten logos as voted by the Amazon Mechanical Turks were:

Entry IDVotesURL

88

76

http://99designs.com/contests/24619/entries/88

78

65

http://99designs.com/contests/24619/entries/78

75

60

http://99designs.com/contests/24619/entries/75

87

55

http://99designs.com/contests/24619/entries/87

91

51

http://99designs.com/contests/24619/entries/91

58

48

http://99designs.com/contests/24619/entries/58

47

42

http://99designs.com/contests/24619/entries/47

90

41

http://99designs.com/contests/24619/entries/90

43

36

http://99designs.com/contests/24619/entries/43

Personally, I like the top ten logos and my Dad’s staff seems to like many of the same logos that were voted up. It’s been an interesting experiment almost exclusively using the “crowd” to design and then select a logo. I’m not sure if we’ll use 99designs in the future but it has been a pleasant experience.

We still haven’t picked a winning logo but I’ll update once we do!

Update:

We finally picked a winner! We decided to go with the crowd and selected http://99designs.com/contests/24619/entries/88 as the winning logo.

Extracting text from PDFs without pdftotext

For a recent project, I had to extract the text out of a PDF so that I could save it into a database table.

Normally, I would of used the popular pdftotext program but it wasn’t available in the particular environment I was working in. I contact support and they advised that the http://www.foolabs.com/xpdf/">XPDF package has several X windows dependencies and that’s why they had not installed it. Fair enough.

I poked around a bit and found Apache’s http://incubator.apache.org/pdfbox/">PDFBox library. I downloaded the package and looked at the examples. Sure enough there was a program called “ExtractText” that did exactly what I wanted.

Using ExtractText is similar to pdftotext - just pass in the PDF file and the text comes back. Awesome.

Anyway, hats off to Ben Litchfield who wrote the ExtractText example. I rebuilt the ExtactText.java file as a standalone project and packaged it as a JAR.

I’ve attached the JAR and Eclipse project if anyone wants a copy of either.

The JAR

The Eclipse Project

Monkeys and shakespeare: genetic algorithms with Jenes

The other night at a bar, we started talking about evolution which somehow sparked a discussion about the law of large numbers and the probability that humanity is just a cosmic fluke. Eventually, someone brought up the “monkeys on a typewriter” argument which caused uproar among the philosophers in the group.

This morning, I decided to see what Wikipedia had to say about monkeys and typewriters and eventually stumbled across an article about the “Weasel program” which Richard Dawkins wrote to demonstrate “random variation and non-random cumulative selection in natural and artificial evolutionary systems.” Basically, it simulates the monkeys on a typewriter to produce a line from Hamlet. At this point, I was hooked – I wanted to make one.

I’d experimented with genetic algorithms in a class I took at Tufts and I’ve been increasingly curious since the “evolving Mona Lisa” code got out on the web.

Anyway, I decided to use the Jenes library to whip up some code to “evolve” strings. The Jenes library is absolutely fantastic. It is easy to setup, easy to use, and the documentation is well written and easy to follow.

My implementation is online at: http://setfive.com/evolve.php

And it evolves Dawkin’s Hamlet line in about 3 seconds - link

The code to run the genetic algorithms is written in Java and uses a Jetty container to accept and processes HTTP requests. Using an embedded Jetty container proved to be seamless and the application server seems to running pretty smoothly.

A zip file containing an Eclipse project for the code is available here

.

Additionally, a self contained JAR for the server is available here

. Start it with java -jar wordga-jetty.jar

As always, questions and comments are welcome.