man-in-the-middleIn my previous blog, I explained how a “middle man” can negotiate peace between two enemies, by being an intermediate link, in a computer network. This allows for “natural enemies” to collaborate with each other, and exchange high-value data, without even knowing that’s what they’re doing. All of this, inside a “web of trust”, where each participant exclusively exchange data with a server whom he trusts, which results in reducing the bullshit-2-intelligence ratio on the World Wide Web, by several orders of magnitudes.

Below is the code I used for my demo. But before I give you the code, realize that this code will not work when using Phosphorus.Five, as of this writing (30th of March 2015), since the Phosphorus release necessary to execute the code, is not yet released. It can however be found in the Phosphorus.Five main GIT branch over at GitHub.

If you’d like to test it out yourself, then you’re going to have to create three new “pf.lambda pages” using the “pf.page editor” in System42.

Here is the first page you’re going to have to create, which should have the url of “/john-doe”;

/*
 * creating an Ajax Web Widget
 * containing 4 child widgets
 */
pf.web.widgets.create
  class:span-12 prepend-6 info prepend-top
  widgets

    // header
    literal
      element:h1
      innerValue:"This might seem booring ..."

    // some dummy paragraph
    literal
      innerValue:"Until you read the fine print ... ;)"

    // text box form input element
    void:txt
      element:input
      type:text
      class:span-6 title
      placeholder:Search for something ...

    // button that initiates our HTTP web request
    literal:execute
      element:button
      class:clear span-3
      innerValue:Click me!
      onclick

        // retrieving the value of our text box
        pf.web.widgets.property.get:txt
          value

        // creating our HTTP web request
        // notice that this will be transferred as
        // both encrypted and signed, using PGP
        pf.net.create-request:"http://127.0.0.1:8080/some-other-website"
          method:post
          headers
            Content-Type:multipart/mixed

          // if you remove the next node, then "Frank" will
          // no longer trust the caller, and return some "dummy data"
          sign:john@somewebsite.com
            password:foobar

          // If you change the email below to
          // bob@yetanotherwebsite.com, and you
          // change the URL above, in the [pf.net.create-request]
          // node above to "/yet-another-website", then you will no
          // longer go through your "data broker" (Frank), but
          // go directly to Bob, which illustrates how Bob then
          // can inject malicious code on your server ...
          encrypt
            :frank@someotherwebsite.com
          decryption-password:foobar
          argument:@/../*/pf.web.widgets.property.get/*/txt/*?value
            Content-Type:text/Hyperlisp
            Content-Disposition:inline; name=foo-bar
        // creating a pf.lambda node tree from the return value
        // from Frank, and executing that pf.lambda code
        append:@/+?node
          source:@/../**/return-value?value
        _hpl
        lambda:@/-?node

The second webpage you’re going to have to create must have the URL of “/some-other-website”;

/*
 * retrieving raw bytes from HTTP request
 */
pf.web.request.get-body

/*
 * decrypting content
 */
pf.crypto.pgp.decrypt:@/-/0?value
  password:foobar

/*
 * verifying the signature of the MIME message
 */
pf.crypto.pgp.verify-signature:@/../1/1?value

/*
 * checking that this was signed by "John"
 */
if:"@/-/0/=:bool:true/0?value"
  =:john@somewebsite.com
  lambda

    /*
     * parsing the MIME message after decrypting it
     * and verifying its signature
     */
    pf.mime.parse-mime:@/../1/1?value

    /*
     * invoking third party Web Service,
     * vouching for the caller!
     */
    pf.net.create-request:"http://127.0.0.1:8080/yet-another-website"
      method:post
      headers
        Content-Type:multipart/mixed
      /*
       * if you remove the signature below from the HTTP request,
       * then "Bob" will no longer trust the caller, and return
       * "malicious code" ...
       */
      sign:frank@someotherwebsite.com
        password:foobar
      encrypt
        :bob@yetanotherwebsite.com
      decryption-password:foobar
      foo-bar:@/./-/**/foo-bar/?value
        Content-Type:text/Hyperlisp
        Content-Disposition:inline; name=foo-bar

    /*
     * making sure we echo our response as "multipart/mixed"
     */
    pf.web.response.headers.set:Content-Type
      source:multipart/mixed

    /*
     * echo the return value from "yet-another-website"
     * back to caller
     */
    pf.web.response.echo
      sign:frank@someotherwebsite.com
        password:foobar
      encrypt
        :john@somewebsite.com
      return-value:@/./-2/**/return-value?value
        Content-Type:text/Hyperlisp
        Content-Disposition:inline; name=return-value
else

  /*
   * making sure we echo our response as "multipart/mixed"
   */
  pf.web.response.headers.set:Content-Type
    source:multipart/mixed

  /*
   * since this email was not signed by "John",
   * we return a piece of code explaining that
   * to the caller, and we do not pass the request
   * onwards to "Bob".
   */
  pf.web.response.echo
    sign:frank@someotherwebsite.com
      password:foobar
    encrypt
      :john@somewebsite.com
    return-value:@"pf.web.create-widget
  widget:literal
  element:h1
  class:span-12 prepend-6 error
  innerValue:You're not my friend dude!!"
      Content-Type:text/Hyperlisp
      Content-Disposition:inline; name=return-value

And the third page you’ll need, must be have the url of “/yet-another-website”;

/*
 * retrieving raw bytes from HTTP request
 */
pf.web.request.get-body

/*
 * decrypting content
 */
pf.crypto.pgp.decrypt:@/-/0?value
  password:foobar

/*
 * verifying the signature of the MIME message
 */
pf.crypto.pgp.verify-signature:@/../1/1?value


/*
 * making sure we echo our response as "multipart/mixed"
 */
pf.web.response.headers.set:Content-Type
  source:multipart/mixed

/*
 * checking that the message was signed by 
 * "Frank"
 */
if:"@/-2/0/=:bool:true/0?value"
  =:frank@someotherwebsite.com
  lambda

    /*
     * parsing the MIME message after decrypting it
     * and verifying its signature
     */
    pf.mime.parse-mime:@/../1/1?value

    /*
     * executing the code given from "some-other-website"
     * and returning the results
     */
    pf.web.response.echo
      sign:bob@yetanotherwebsite.com
        password:foobar
      encrypt
        :frank@someotherwebsite.com
      return-value:@"pf.web.widgets.create
  class:info span-12 prepend-top prepend-6
  widgets
    literal
      element:h2
      innerValue:Hello from the other side of the World!
      onclick
        pf.web.widgets.create
          element:h3
          widget:literal
          class:success span-12 prepend-top prepend-6
          innerValue:""Ohh yeah, almost forgot. Sorry, I couldn't find '{0}'. Have a nice day :)"""
        :@/././-/**/foo-bar?value
        Content-Type:text/Hyperlisp
        Content-Disposition:inline; name=return-value
else

  /*
   * Since "John" is the only one we trust,
   * we return "malicious code" unless the request
   * originates from "John".
   */
  pf.web.response.echo
    sign:bob@yetanotherwebsite.com
      password:foobar
    encrypt
      :john@somewebsite.com
    return-value:@"pf.web.widgets.create
  class:info span-12 prepend-top prepend-6
  widgets
    literal
      element:h2
      innerValue:Hello from the other side of the World!
      onclick
        pf.web.widgets.create
          widget:literal
          element:h3
          class:error span-12 prepend-top prepend-6
          innerValue:""YOU ARE NOT MY FRIEND!! I HAVE NOW STOLEN ALL YOUR DATA, AND INSTALLED A VIRUS ON YOUR SERVER!!!"""
      Content-Type:text/Hyperlisp
      Content-Disposition:inline; name=return-value

And that’s it. In addition to these three pages in your System42 installation, you’re also going to need three private key pairs, which can easily be created on Linux by using KGpg. It is important that these three key pairs all have the password of “foobar”, and that they have the email address of “john@somewebsite.com”, “frank@someotherwebsite.com” and “bob@yetanotherwebsite.com”.

Then you can click “preview” for your “/john-doe” website in the “pf.page editor”, and type something into the text box, before you click the button. When you do, an Ajax request will be initiated to the server, which will execute the “onclick” event handler. This event handler will create an HTTP Web Service Request using REST and POST as its mechanism. The data transferred to the Web Service will be a cryptographically signed and encrypted MIME message. Then the Web Service receiver, will decrypt the message, verify the signature, and re-transmit that message to another Web Service (belonging to Bob). Notice that also “Frank” will encrypt the message, and sign it, before passing the invocation onwards to “Bob”. This means that all parties have a guarantee of that the message came from only people they trusted. In addition, all data transferred over the wire is encrypted!