Make your backend service OCN-ready (OCPI 2.2 API + OCN Signature)

The Open Charging Network acts as a decentralized hub based on the Open Charge Point Interface. To connect your backend service (e.g. as Charge Station Management System or eMobility Service Provider backend) to the Open Charging Network you need to have a OCPI 2.2-ready API. Please visit the OCPI Github to learn more.

To be sure that every OCPI message is not modified without our permission during its transit, the Open Charging Network requires that every OCPI message is signed by its sender*. This is achieved by implementing the OCN Signature in your OCPI 2.2 interface. Any node of the Open Charging Network production environment requires application of the OCN Signature, otherwise your OCPI messages will not get transmitted.

*In fact, OCN Node Operators can optionally disable the requirement for signed messages. However, we strongly advise not to run OCN Nodes on the Production Environment without message signing enabled.

The OCN Signature

Taking a cue from the blockchain community, we have developed a message signing and verifying system for the Open Charging Network. Under the hood it uses the Elliptic Curve Digital Signature Algorithm (ECDSA) as implemented by Ethereum. The signature itself holds a JSON Object containing all the necessary data for the recipient to verify the data it is receiving. Not only do requests need to be signed, but responses too.

For requests, the signature is appended to the outgoing OCPI 2.2 headers:

1 2 3 4 5 6 7 8 Authorization: Token 0ea32164-515f-418b-8bef-39f3817ea090 X-Request-ID: 71d62c5b-5017-493e-be00-3f5ad4e34fff X-Correlation-ID: 9881b6f7-63aa-40d2-b9c2-d6daa69c11fb OCPI-From-Country-Code: CH OCPI-From-Party-Id: MSP OCPI-To-Country-Code: CH OCPI-To-Party-Id: CPO OCN-Signature: eyJmaWVsZHMiOlsiJFsnaGVhZGVycyddWyd4L (truncated)...

For responses, the signature is appended to the outgoing OCPI 2.2 JSON response body:

1 2 3 4 5 6 { "status_code": 1000, "data": { "result": "ACCEPTED" }, "timestamp": "2020-03-02T12:48:33.005Z", "ocn_signature": "eyJmaWVsZHMiOlsiJFsnaGVhZGVycyddWyd4L (truncated)..." }

The idea is that the recipient can use this signature to verify that the message has been signed correctly and has not been modified by an unauthorized party. What do we mean by unauthorized? For the OCN to function properly, there are cases where an intermediary (i.e. an OCN node) needs to modify the request/response. Such an example would be the response_url in the JSON body of requests made to the receiver interface of the OCPI commands module. As the recipient does not have access to the response_url defined by the sender, the OCN Node must modify the value. In an OCN signature, this is known as “stashing”. The signature object contains the history of rewrites, with the previous signature being stashed by the party modifying the data. When a recipient then verifies a signature, the rewrites are also verified.

Let’s take a closer look at what the signature actually is:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 interface Signature { val fields: Array<String> val hash: String val rsv: String val signatory: String val rewrites: Array<Rewrite> } interface Rewrite { val rewrittenFields: Map<String, Any?> val hash: String val rsv: String val signatory: String }

The signature itself contains everything needed to verify the most-recent version of the sent data, i.e. by the sender or OCN node depending on whether any values needed to be modified. Provided is a list of jsonpath fields which can be used to recreate the message as signed by the sender, with the original order of values preserved. The values are hashed using keccak-256, as implemented by Ethereum. The resultant hash is actually the message which is signed. The RSV is the signature, produced by ECDSA using an Ethereum wallet’s private key. The signatory refers to the address of the wallet that was used to sign the message.

The list of rewrites contains an object containing the previous hash, rsv and signatory. It also allows the original message to be recreated by storing the fields which have been rewritten. For example, a commands receiver request might have the following rewrite by the OCN node:

1 2 3 4 5 6 Rewrite( rewrittenFields = mapOf("$['body']['response_url']" to "https://emsp.net/ocpi/2.2/sender/commands/START_SESSION/acfbb8d2-bd49-4837-97e2-d2c38f6bae55"), hash = "0x1ce93f156bc5b3a5c26c5f2499db7bfa2b38c37fd32616fc6487175b86f41eb2", rsv = "0x16e8b9c4e44f4646235fca85a594b5a31057930676d338d111ae985a4f0d9d4214705a0a2ae18c4dfd014581e96eb4625137a937853d4b2d17a0f3a22750f6ac1c", signatory = "0x25e4fca0a0e5107d06d71ed78f687827208d5ff9" )

 

The Signatory

 Of course, the signatory of both the OCN Signature and its rewrites should be independently validated. The verification of the signature only tells us that the message was signed by the signatory provided. The signatory itself could be any Ethereum wallet address. The address of both the original sender and their OCN node can be found in the OCN Registry.

 

The OCN Notary

Now that we know how the signature functions, how do we actually use it? Enter the OCN Notary.

The OCN Notary implements the above Signature and Rewrite interfaces. It can deserialize an incoming OCN Signature and verify its contents. It can be used to sign an OCPI request, and likewise to stash/rewrite values in a request.

Currently the Notary library is available as an NPM package and as a Maven package for languages targeting the JVM. Head on over to the OCN Notary repository to find more information for each package.

 

Open API 3.0 Specs for version 1.0 of the Open Charging Network

You can find the specification document in the OCN Node repository, here: Open API 3.0 specs

Using this specification, it is possible to generate client code and test implementations. For more information, see https://swagger.io/docs/specification/about/.

Note that this document was generated using unmodified source code in the master branch. As such, certain features of the specification format might be missing, such as examples for HTTP requests and responses.