Signing JSON Objects

I need to exchange JSON objects between different platforms and implementations of the service and make its integrity verifiable through digital signatures. Thus, platform A will create such an object and create a digital signature. The specified signature is then included in the object and sent to platform B. JSON objects can contain arbitrary attributes and data.

eg. in PHP:

function signObject($jsonObjectToSign, $privateKey) { $jsonObjectToSign->signature = ""; $msgToSign = json_encode($jsonObjectToSign); openssl_sign($msgToSign, $jsonObjectToSign->signature, $privateKey, OPENSSL_SLGO_SHA1); return $jsonObjectToSign; } 

The problem is that, for example, in Java there is no way to determine whether the attributes of the JSON object will be in the same order in which you added them (via JSONObject.put ()). So if i do

 $json = json_encode('{"a":1, "b":2}'); 

in PHP, sign this object as described above, transfer it to a Java-based server, decode the json object, and then try to verify the signature, I would probably get a different order of object attributes.

So what I need is a reliable way to create a String from a JSONObject, regardless of the language or platform used.

The above example should always output {"a":1, "b":2} and NEVER {"b":2, "a":1} . Unfortunately, this is a common case, for example. in java.

Is there a โ€œbest practiceโ€ for safely signing JSON objects?

But let me describe the problem differently:

Say I want to do this in Java (or any other language):

 JSONObject j = new JSONObject(); j.put("a", 1); j.put("b", 2); 

Now I need a serialization function that always displays the same string representation for this object, no matter how and with what language this object is created.

+6
source share
4 answers

This is how I solved it now. This is somehow similar to what JOSE does, with the exception of the header. But JOSE seems to bring a lot of overhead (and features) that I don't need. So I decided to go with the following:

 class Signature { private static $algorithm = OPENSSL_ALGO_SHA512; private static $signaturePrefix = '-----BEGIN SIGNATURE-----'; private static $signaturePostfix = '-----END SIGNATURE-----'; public static function createSignature($message, $privateKey) { $signature = null; openssl_sign($message, $signature, $privateKey, self::$algorithm); return self::$signaturePrefix . base64_encode($signature) . self::$signaturePostfix; } public static function verifySignature($message, $publicKey, $signature) { $signature = str_replace(self::$signaturePrefix, '', $signature); $signature = str_replace(self::$signaturePostfix, '', $signature); return openssl_verify($message, base64_decode($signature), $publicKey, self::$algorithm); } public static function signJSON($jsonToSign, $privateKey) { if(gettype($jsonToSign) != 'string') $jsonToSign = json_encode($jsonToSign); $signedJSON = json_decode('{}'); $sigedJSON->signature = self::createSignature($message, $privateKey); $signedJSON->object = $jsonToSign; return $signedJSON; } public static function verifyJSONSignature($jsonObject, $publicKey) { if(gettype($jsonObject->object) == 'string') throw new Exception('Value $jsonObject->object must be a String, is a ' . gettype($jsonObject->object)); return self::verifySignature($jsonObject->object, $publicKey, $jsonObject->signature); } } 
0
source

The signing and encryption of JSON objects is specified in the JOSE specification set, where JOSE stands for Javascript Object Signing and Encryption, see http://jose.readthedocs.org/en/latest/ JOSE uses a dedicated signature computed over the base64url encoding representation of the JSON object. The signature is not part of the JSON object itself, so no override is required to verify it.

+3
source

Since AFAIK does not have an official (nor unofficial) standard in JSON Signing, I would probably follow the usual implementation. I would define a new JSON object, for example.

 { "original": "..." // original JSON as a Base64 encoded string "signature": "..." // the signature } 

and implement a signature / signature verification layer on both sides of my system.

+2
source
 JsonObject js = new JsonObject(); js.addProperty("c", "123"); js.addProperty("t", "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); System.out.println("Json object == " + js); GenerateSignature util = new GenerateSignature(); String ecodedToken = util.signJSONObject(js); 
-1
source

All Articles