Subject: [apps-discuss] JSON encoding of binary objects

From: Phillip Hallam-Baker <[email-masked]>
Date: Fri, 21 Sep 2012 11:32:51 -0400

Here is what I do in Omnibroker, an example message is:

HTTP/1.1 203 Passcode
Content-Type: application/json;charset=UTF-8
Content-Length: 500

{
  "OpenResponse": {
    "Status": 203,
    "StatusDescription": "Passcode",
    "Cryptographic": [{
        "Secret": "xlE2Bu6cMf3Y9x29tsP5WQ==",
        "Encryption": "A128CBC",
        "Authentication": "HS256",
        "Ticket":
        "hyBNCDyVadjnkSzNp4goyQ+QR9jw/TnF5jQrkl66QhQbcfxSfTj+kxjzWt
        3s6z9X2KMziSerHpLmw7DPoCg8OM1MHSt5PHHssfPvH6eaU+PxREiqMMFSI
        7k9MFh53dTWJ8Sp6Q+/dN9LnvwgZ5P83w=="}],
    "Challenge": "PrE0hkZefumcw17yuYHz+w==",
    "ChallengeResponse": "0lXrJqm6JmeWoCGmoV3Yhg=="}}

The values 'secret' and 'ticket', 'Challenge' and 'ChallengeResponse' are
defined as binary data in the schema and represented as strings containing
Base64 encoded data. [Note that the secret is currently required to be
passed over a TLS channel, may well add further protection such as a DH
exchange later so as to guarantee end-to-endness]

I see no need to change JSON encoding rules to add binary. The data format
does not need to be self describing.

The schema for the message is:

Message OpenResponse
Inherits BindResponse

Binary Challenge
Description
|Challenge value to be used by the client to respond
|to the server authentication challenge.
Binary ChallengeResponse
Description
|Server response to authentication challenge by the client
|as described in section <xref target="ChallengeResponse"/>
Struct ImageLink VerificationImage
Multiple
Description
|Link to an image to be used in an image verification mechanism.
Description
|An Open request MAY be accepted immediately or be held pending
|completion of an inband or out-of-band authentication process.
Description
|The OpenResponse returns a ticket and a set of cryptographic
|connection parameters in either case. If the
Status Complete
|The OpenRequest was accepted and the binding parameters
|specified are now active.
Status Pending
|The OpenRequest is being held pending offline verification
|of the parameters.
Status Passcode
|The OpenRequest is being held pending completion of the
|passcode authentication mechanism.

Note that the schema supports inheritance, I have left out the parent class
for brevity but it is in the (attached) definition file.

This is a tool that I have written mostly for my own use so it is possibly
a little rougher than it should be. I think that it is probably useful to
be able to distinguish request messages from response messages.

I did think about defining protocol flows as a state machine. But 95% of
protocol messages end up as request-response queries.

The C# class that is generated looks like the following:

public partial class OpenResponse : BindResponse {
public byte[] Challenge;
public byte[] ChallengeResponse;
public List<ImageLink> VerificationImage;

static string _Tag = "OpenResponse";
public override string Tag () {
return _Tag;
}

public OpenResponse () {
}
public OpenResponse (JSONReader JSONReader) {
Deserialize (JSONReader);
}
public OpenResponse (string _String) {
Deserialize (_String);
}

public override string ToString () {
...
}

public new void Serialize (Writer Writer) {
Serialize (Writer, false);
}

public new void Serialize (Writer Writer, bool tag) {
...
}

public new void Serialize (Writer Writer, bool wrap, ref bool first) {
...
}
}

Converting the tool to generate Java would be pretty simple. The only part
that would be a little clunky is that Java does not have the concept of a
partial class which C# has. This is very useful for developing code
generation tools as it means that the programmer can extend the
automatically generated class in a separate file. Working with code
generation tools in Java is a lot less friendly.

Converting to generate C would mean flattening out the inheritance tree for
each structure.

The generator itself consists of a schema file (220 lines) and a script
(750 lines). So the total code generator is less than 1000 lines. There is
also another 2000 or so lines of generic support library code to do things
like call up the DateTime conversion, escape strings and the lexer for the
parser.

The generator is in turn generated using Goedel which is about the same
size.

---

From: Julian Reschke <[email-masked]>
Date: Fri, 21 Sep 2012 17:53:34 +0200

> Here is what I do in Omnibroker, an example message is:

203? Really?

Best regards, Julian

---

From: Phillip Hallam-Baker <[email-masked]>
Date: Fri, 21 Sep 2012 12:08:58 -0400

That should be 202 or 200, not decided which yet.

ProtoGen not define the HTTP status codes right now. I I did implement them
it would be as part of a state machine describing the client and server
side operations. The issue that appeared when I tried to do that is that
the state machine for the client and server are very different. In fact the
server protocol is intentionally stateless. The server side state is
bundled into the ticket.

-- 
Website: http://hallambaker.com/