N/A
Introduction
YASMIN (Yet Another jSon Message notatIoN), was designed to offer an alternative to REST based APIs, by bringing the following enhancements to the table:
Note: If you are looking for an API you won't find one because YASMIN is a message-centric concept, where "self-sufficient" messages using JSON syntax have been "liberated" from interfering HTTP bindings, URIs, and clunky SOAP envelopes. However, nothing prevents you from mapping APIs into messages!
Use Cases
Although YASMIN was initially created for security-related client-applications like "wallets", credential enrollment, etc., it should be equally applicable for quite different tasks including bank-to-bank transactions.
Aided by WebSockets, high-performance, interactive Web applications also seem to be in scope, in particular those building on the SPA concept.
Message Structure
One of the requirements (derived from XML and XML Schema), was the ability recognizing the type of a message (object) by including such information in the message itself. This allows you to process different messages through a single dispatcher mechanism as well as easing debugging and documentation.
The following sample message from the Saturn project shows the YASMIN typing scheme:
{
    "@context": "https://webpki.github.io/saturn/v3",
    "@qualifier": "PayeeAuthority",
    "authorityUrl": "https://payments.bigbank.com/payees/86344",
    "providerAuthorityUrl": "https://payments.bigbank.com/authority",
    "localPayeeId": "86344",
    "commonName": "Demo Merchant",
    "homePage": "https://demomerchant.com",
    "accountVerifier": {
        "algorithm": "S256",
        "hashedPayeeAccounts": ["kUwpqk-cbkDaBjwDD_etPSh_FtC-Ap2K_A2MQzXNy_U", "hMALZWfHmLNN0fzWjWZisF_0y4Q4M_p7pJsULyg1xWM"]
    },
    "signatureParameters": [{
        "algorithm": "ES256",
        "publicKey": {
            "kty": "EC",
            "crv": "P-256",
            "x": "_7bQ8JTt6_r1lh46kwmwypqMkZOJ0cYs-w2LHWOYt5M",
            "y": "tLcyLWDQoAk4cMaWY7BdV3JaywQQoLxO2WQ30Klj6fc"
        }
    }],
    "timeStamp": "2020-03-21T08:02:30Z",
    "expires": "2020-03-21T09:02:31Z",
    "issuerSignature": {
        "algorithm": "ES256",
        "publicKey": {
            "kty": "EC",
            "crv": "P-256",
            "x": "-Vr8Wk3ygt5J2_J3R8TrRaa-AWW7ZiXa6q1P7ELs6gc",
            "y": "Vuc6z3WiZ3tgXTXvU6F5qdiiYePWeUI1q9Tx83ySDcM"
        },
        "value": "OcRz5yxFFa_lJZ03czji6d4GUpPPBXRI....PmpuRR8N5UUfDhdlJjTUB_yZkd1rCK1w"
    }
}
Explanation: The @context property is essentially a counterpart to an XML name-space, while @qualifier emulates an XML top-level element. In a typical implementation @context is a URI constant identifying "audience", transport method, security considerations, etc., while @qualifier denotes actual message type.
The point with having designated "keywords" for type information is for enabling creation of YASMIN tools as well as facilitating automatic object instantiation.
A major advantage with typed (and self-contained) messages is that they become transport-independent, allowing them to be embedded in HTML pages, sent over NFC, or be pushed through various proxies without losing their meaning.
Sending Messages over HTTP
Requests containing YASMIN messages must be invoked by HTTP POST, while requests that only lookup existing data may also use GET (and any for the application suitable URI scheme including REST).
Successful requests including "soft" (handled) errors like "Insufficient Funds" should return HTTP 200, while "hard" (non-recoverable) errors should return an applicable HTTP 4xx or 5xx status code, plus a suitable text message for logging and debugging purposes.
POSTed messages should preferably be idempotent within their validity time to facilitate secure retransmissions.
Below is an example of a POSTed transaction request:
POST /transact HTTP/1.1
User-Agent: Java
Host: saturn.mybank.com
Content-Type: application/json                                   Mandatory MIME type
Content-Length: 1234

{
  "@context":"some-name-space",
  "@qualifier":"some-object-type",

       Additional Transaction Payload Request Properties

  "signature":{...}                                              Optional signature
}
GET and POST responses follow the same pattern:
HTTP/1.1 200 OK
Content-Type: application/json                                   Mandatory MIME type
Content-Length: 9541

{
  "@context":"some-name-space",
  "@qualifier":"some-object-type",

       Additional Response Properties

  "signature":{...}                                              Optional signature
}
If the HTTP "Accept" header is defined it must only contain a single "application/json" property.
Message Serialization and Deserialization (Parsing)
JSON String = JSON.stringify(JavaScript Object);     // Hey, I don't like complexity!
JavaScript Object = JSON.parse(JSON String); // Me neither :-)
Signed Messages
The vision was to have something similar to XML DSig but preferably not depending on megabytes of fairly intricate library code. Using the IETF JOSE suite of JSON based cryptographic standards would have been cool, but the JOSE signature scheme forces you encoding messages in Base64Url which do not only make messages unreadable by humans, but worse, disrupts the YASMIN message typing scheme.
Since existing JSON signature solutions did not match YASMIN, a new signature scheme had to be developed which (completely unintentional), turned out to be compatible with recent versions of JavaScript as well!
The signature system is described in: https://cyberphone.github.io/doc/security/jsf.html.
To maintain a "style compatible" messaging concept, a matching encryption scheme was also added to the plot: https://cyberphone.github.io/doc/security/jef.html.
Due to the fact that YASMIN messages are based on pure JSON, countersigning and embedding previous requests do not require any special arrangements.
Message Handlers and Decoders
The devised scheme does not specify whether all requests should go to a single handler (e.g. Java Servlet) and URI, but in the case a handler supports more than one message type you need to dispatch messages to the appropriate sub-handler. This is trivial using typed messages here expressed in JavaScript:
var input = JSON.parse(readRequest(request));      // Hypothetical method: "readRequest()"
if (input['@context'] != 'https://example.com/system') {
  throw new TypeError('Unrecognized Type');
}
var output;
switch (input['@qualifier']) {
  case 'Authorize':
    output = authorize(input);                     // Handler
    break;
  case 'CommitPayment':
    output = commitPayment(input);                 // Handler
    break;
  default:
    throw new TypeError('Unrecognized Message');
}
writeResponse(response, JSON.stringify(output));   // Hypothetical method: "writeResponse()"
Mapping Messages into APIs
In case you prefer APIs before messages, the following fictitious example in Java illustrates how this could be achieved using YASMIN:
@YService("https://iotstandards.org/device")
public class MyService {

    @YMethod
    @YSimpleReturn("currentValue")
    public double setFurnaceTemperature(@YParam("deviceId") String deviceId, 
                                        @YParam("value") double value) throws IOException {

        Actual method code...

    }
}
A request message would presumably look like the following:
{
    "@context": "https://iotstandards.org/device",
    "@qualifier": "setFurnaceTemperature",
    "deviceId": "#3407-B",
    "value": 223.5
}
A matching response would then be:
{
    "@context": "https://iotstandards.org/device",
    "@qualifier": "setFurnaceTemperature#R",
    "currentValue": 104.2
}
Note: At the time of writing there are currently no specific tools available for creating YASMIN based APIs.
Security Considerations
The security and privacy characteristics of YASMIN based systems are no worse (or better) than offered by the underlying transport and the quality of the implementation.
Using signed messages is recommended for integrity and authentication purposes (if possible in the actual scenario).
HTTP requests should use TLS (HTTPS) to cater for privacy and end-point authentication.
Implementations
Unsigned YASMIN messages can be created with any JSON tool.
Signed YASMIN messages need specific library support, currently only available on GitHub:
LanguageURL
Javahttps://github.com/cyberphone/openkeystore#api
Node.jshttps://github.com/cyberphone/node-webpki.org
Pythonhttps://github.com/cyberphone/openkeystore/tree/master/python
Document History
DateVerComment
2017-01-270.5Initial publication in HTML5
2017-04-160.6Changed public keys to use JWK format
2020-02-030.61Updated references
Author
Anders Rundgren (anders.rundgren.net@gmail.com), WebPKI.org