Subversion Repositories oidplus

Rev

Rev 868 | Rev 897 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
868 daniel-mar 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)
871 daniel-mar 81
        // Note that the required "alg" argument will be added automatically
868 daniel-mar 82
        $header = [
871 daniel-mar 83
                "typ" => "OID-IP", // optional (unused)
84
                "cty" => "text/json" // optional
868 daniel-mar 85
        ];
86
        $payload = $canonical;
87
        $jws->setPrivateKey($privkey, '');
88
        $signature = $jws->sign($payload, $header);
89
 
90
        // 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.
91
        $output = $input;
92
        $output->signature = $signature;
93
 
94
        // Self-test and output
95
        $json_signed = json_encode($output);
96
        oidplus_json_verify($json_signed, $pubkey);
97
        return $json_signed;
98
}