Subversion Repositories oidplus

Rev

Rev 871 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. <?php
  2.  
  3. /*
  4.  * OIDplus 2.0
  5.  * Copyright 2019 - 2022 Daniel Marschall, ViaThinkSoft
  6.  *
  7.  * Licensed under the Apache License, Version 2.0 (the "License");
  8.  * you may not use this file except in compliance with the License.
  9.  * You may obtain a copy of the License at
  10.  *
  11.  *     http://www.apache.org/licenses/LICENSE-2.0
  12.  *
  13.  * Unless required by applicable law or agreed to in writing, software
  14.  * distributed under the License is distributed on an "AS IS" BASIS,
  15.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16.  * See the License for the specific language governing permissions and
  17.  * limitations under the License.
  18.  */
  19.  
  20. // Works with composer.json
  21. // "sergeybrook/php-jws": "^1.0"
  22.  
  23. require_once __DIR__.'/vendor/aywan/php-json-canonicalization/src/Utils.php';
  24. require_once __DIR__.'/vendor/aywan/php-json-canonicalization/src/JsonCanonicalizationInterface.php';
  25. require_once __DIR__.'/vendor/aywan/php-json-canonicalization/src/JsonCanonicalizationFactory.php';
  26. require_once __DIR__.'/vendor/aywan/php-json-canonicalization/src/Canonicalizator.php';
  27.  
  28. function oidplus_json_verify($json_content, $pubkey) {
  29.         require_once __DIR__.'/vendor/autoload.php';
  30.  
  31.         $jws = new \SBrook\JWS\JwsRsa();
  32.  
  33.         // Load JSON
  34.         $json = json_decode($json_content);
  35.  
  36.         // 1. Extract the contents of the "signature" key from the JSON.
  37.         $signature = $json->signature;
  38.  
  39.         // 2. Remove the "signature" key from the JSON
  40.         unset($json->signature);
  41.  
  42.         // 3. Canonize the JSON contents using RFC 8785
  43.         $canonicalization = \aywan\JsonCanonicalization\JsonCanonicalizationFactory::getInstance();
  44.         $canonical = $canonicalization->canonicalize($json);
  45.         $actual_payload = $canonical;
  46.  
  47.         // 4. Compare the canonized JSON to the base64-encoded payload of the JSON Web Signature.
  48.         $expected_payload = $jws->getPayload($signature);
  49.         if ($actual_payload != $expected_payload) {
  50.                 // echo "Actual:\n\n$actual_payload\n\n";
  51.                 // echo "Expected:\n\n$expected_payload\n\n";
  52.                 throw new Exception("Signature verification failed (Payload different)");
  53.         }
  54.  
  55.         // 5. Verify the JSON Web Signature according to RFC 7515
  56.         $jws->setPublicKey($pubkey);
  57.         $v = $jws->verify($signature);
  58.         if (!$v) {
  59.                 throw new Exception("Signature verification failed!");
  60.         }
  61. }
  62.  
  63. function oidplus_json_sign($json_content, $privkey, $pubkey) {
  64.         require_once __DIR__.'/vendor/autoload.php';
  65.  
  66.         $jws = new \SBrook\JWS\JwsRsa();
  67.  
  68.         // Load JSON
  69.         $input = json_decode($json_content);
  70.  
  71.         // 1. Make sure that the JSON file has no signature (remove "signature" key if one exists).
  72.         unset($input->signature);
  73.  
  74.         // 2. Canonize the JSON contents using RFC 8785
  75.         $canonicalization = \aywan\JsonCanonicalization\JsonCanonicalizationFactory::getInstance();
  76.         $canonical = $canonicalization->canonicalize($input);
  77.  
  78.         // 3. Sign the canonized JSON using a JSON Web Signature (JWS, RFC 7515)
  79.  
  80.         // For JWS registered header parameter names see (RFC 7515, Section 4.1)
  81.         $header = [
  82.                 "typ" => "JSON",
  83.                 "cty" => "text/json"
  84.         ];
  85.         $payload = $canonical;
  86.         $jws->setPrivateKey($privkey, '');
  87.         $signature = $jws->sign($payload, $header);
  88.  
  89.         // 4. Add the key "signature" into the final JSON. Note that the final JSON does not need to be canonized. It can be pretty-printed.
  90.         $output = $input;
  91.         $output->signature = $signature;
  92.  
  93.         // Self-test and output
  94.         $json_signed = json_encode($output);
  95.         oidplus_json_verify($json_signed, $pubkey);
  96.         return $json_signed;
  97. }
  98.