SQLite3 での NULL および DEFAULT 制約の振る舞い、それと PRAGMA TABLE_INFO の dflt_value の値

動作確認環境

  • SQLite 3.37.0

振る舞いの確認

「NOT NULL」指定なし、「DEFAULT NULL」指定なし

sqlite> .schema test1
CREATE TABLE IF NOT EXISTS "test1" (
    "id"    INTEGER,
    "name"  TEXT,
    "number"    INTEGER,
    PRIMARY KEY("id" AUTOINCREMENT)
);
sqlite> INSERT INTO test1 (name, number) VALUES ('Smith', 10);
sqlite> INSERT INTO test1 (name) VALUES ('Smith');
sqlite> INSERT INTO test1 (number) VALUES (30);
sqlite> .mode box
sqlite> .nullvalue (NULL)
sqlite> SELECT * FROM test1;
┌────┬────────┬────────┐
│ id │  name  │ number │
├────┼────────┼────────┤
│ 1  │ Smith  │ 10     │
│ 2  │ Smith  │ (NULL) │
│ 3  │ (NULL) │ 30     │
└────┴────────┴────────┘

name, number コラムの定義は NULL なので、値を指定しない場合は NULL が挿入されます。

「NOT NULL」指定あり、「DEFAULT NULL」指定なし

sqlite> .schema test2
CREATE TABLE IF NOT EXISTS "test2" (
    "id"    INTEGER,
    "name"  TEXT NOT NULL,
    "number"    INTEGER NOT NULL,
    PRIMARY KEY("id" AUTOINCREMENT)
);
sqlite> INSERT INTO test2 (name, number) VALUES ('Smith', 10);
sqlite> INSERT INTO test2 (name) VALUES ('Smith');
Error: stepping, NOT NULL constraint failed: test2.number (19)
sqlite> INSERT INTO test2 (number) VALUES (30);
Error: stepping, NOT NULL constraint failed: test2.name (19)

name, number コラムの定義は NOT NULL なので、値を指定しない場合はエラーになります。

sqlite> SELECT * FROM test2;
┌────┬───────┬────────┐
│ id │ name  │ number │
├────┼───────┼────────┤
│ 1  │ Smith │ 10     │
└────┴───────┴────────┘

「NOT NULL」指定あり、「DEFAULT NULL」指定あり

sqlite> .schema test3
CREATE TABLE IF NOT EXISTS "test3" (
    "id"    INTEGER,
    "name"  TEXT NOT NULL DEFAULT NULL,
    "number"    INTEGER NOT NULL DEFAULT NULL,
    PRIMARY KEY("id" AUTOINCREMENT)
);
sqlite> INSERT INTO test3 (name, number) VALUES ('Smith', 10);
sqlite> INSERT INTO test3 (name) VALUES ('Smith');
Error: stepping, NOT NULL constraint failed: test2.number (19)
sqlite> INSERT INTO test3 (number) VALUES (30);
Error: stepping, NOT NULL constraint failed: test2.name (19)

name, number コラムの定義は NOT NULL なので、値を指定しない場合はエラーになります。 DEFAULT NULL は無視されるようです。

sqlite> SELECT * FROM test3;
┌────┬───────┬────────┐
│ id │ name  │ number │
├────┼───────┼────────┤
│ 1  │ Smith │ 10     │
└────┴───────┴────────┘

「NOT NULL」指定なし、「DEFAULT NULL」指定あり

sqlite> .schema test4
CREATE TABLE IF NOT EXISTS "test4" (
    "id"    INTEGER,
    "name"  TEXT DEFAULT NULL,
    "number"    INTEGER DEFAULT NULL,
    PRIMARY KEY("id" AUTOINCREMENT)
);
sqlite> INSERT INTO test4 (name, number) VALUES ('Smith', 10);
sqlite> INSERT INTO test4 (name) VALUES ('Smith');
sqlite> INSERT INTO test4 (number) VALUES (30);
sqlite> SELECT * FROM test4;
┌────┬────────┬────────┐
│ id │  name  │ number │
├────┼────────┼────────┤
│ 1  │ Smith  │ 10     │
│ 2  │ Smith  │ (NULL) │
│ 3  │ (NULL) │ 30     │
└────┴────────┴────────┘

name, number コラムの定義は NULL なので、値を指定しない場合は NULL が挿入されます。

PRAGMA TABLE_INFO の確認

「NOT NULL」指定なし、「DEFAULT NULL」指定なし

sqlite> PRAGMA TABLE_INFO(test1);
┌─────┬────────┬─────────┬─────────┬────────────┬────┐
│ cid │  name  │  type   │ notnull │ dflt_value │ pk │
├─────┼────────┼─────────┼─────────┼────────────┼────┤
│ 0   │ id     │ INTEGER │ 0       │ (NULL)     │ 1  │
│ 1   │ name   │ TEXT    │ 0       │ (NULL)     │ 0  │
│ 2   │ number │ INTEGER │ 0       │ (NULL)     │ 0  │
└─────┴────────┴─────────┴─────────┴────────────┴────┘

「NOT NULL」指定あり、「DEFAULT NULL」指定なし

sqlite> PRAGMA TABLE_INFO(test2);
┌─────┬────────┬─────────┬─────────┬────────────┬────┐
│ cid │  name  │  type   │ notnull │ dflt_value │ pk │
├─────┼────────┼─────────┼─────────┼────────────┼────┤
│ 0   │ id     │ INTEGER │ 0       │ (NULL)     │ 1  │
│ 1   │ name   │ TEXT    │ 1       │ (NULL)     │ 0  │
│ 2   │ number │ INTEGER │ 1       │ (NULL)     │ 0  │
└─────┴────────┴─────────┴─────────┴────────────┴────┘

「NOT NULL」指定あり、「DEFAULT NULL」指定あり

sqlite> PRAGMA TABLE_INFO(test3);
┌─────┬────────┬─────────┬─────────┬────────────┬────┐
│ cid │  name  │  type   │ notnull │ dflt_value │ pk │
├─────┼────────┼─────────┼─────────┼────────────┼────┤
│ 0   │ id     │ INTEGER │ 0       │ (NULL)     │ 1  │
│ 1   │ name   │ TEXT    │ 1       │ NULL       │ 0  │
│ 2   │ number │ INTEGER │ 1       │ NULL       │ 0  │
└─────┴────────┴─────────┴─────────┴────────────┴────┘

「DEFAULT NULL」を指定した場合は、dflt_value はNULL値ではなく NULL という文字が返ります。

「NOT NULL」指定なし、「DEFAULT NULL」指定あり

sqlite> PRAGMA TABLE_INFO(test4);
┌─────┬────────┬─────────┬─────────┬────────────┬────┐
│ cid │  name  │  type   │ notnull │ dflt_value │ pk │
├─────┼────────┼─────────┼─────────┼────────────┼────┤
│ 0   │ id     │ INTEGER │ 0       │ (NULL)     │ 1  │
│ 1   │ name   │ TEXT    │ 0       │ NULL       │ 0  │
│ 2   │ number │ INTEGER │ 0       │ NULL       │ 0  │
└─────┴────────┴─────────┴─────────┴────────────┴────┘

NULL でないデフォルト値の場合

sqlite> .schema test5
CREATE TABLE IF NOT EXISTS "test5" (
    "id"    INTEGER,
    "name"  TEXT DEFAULT 'Smith',
    "number"    INTEGER DEFAULT 0,
    PRIMARY KEY("id" AUTOINCREMENT)
);
sqlite> PRAGMA TABLE_INFO(test5);
┌─────┬────────┬─────────┬─────────┬────────────┬────┐
│ cid │  name  │  type   │ notnull │ dflt_value │ pk │
├─────┼────────┼─────────┼─────────┼────────────┼────┤
│ 0   │ id     │ INTEGER │ 0       │ (NULL)     │ 1  │
│ 1   │ name   │ TEXT    │ 0       │ 'Smith'    │ 0  │
│ 2   │ number │ INTEGER │ 0       │ 0          │ 0  │
└─────┴────────┴─────────┴─────────┴────────────┴────┘

dflt_value は、文字列の場合 'Smith' のようにシングルクォートで囲まれた値が返ります。

参考

Tags: database, sqlite

CodeIgniter 4.4の処理の流れ

CodeIgniter 4.4の処理の流れをまとめました。

CodeIgniter 4.4 Process Flow

CodeIgniter 4.4 Process Flow

public/index.php

check PHP version
define constant FCPATH
instantiate Config\Paths
  • Config\Paths
    • $systemDirectory
    • $appDirectory
    • $writableDirectory
    • $testsDirectory
    • $viewDirectory
load system/bootstrap.php
  • system/bootstrap.php
    • define constants for directory paths
      • APPPATH
      • ROOTPATH
      • SYSTEMPATH
      • WRITEPATH
      • TESTPATH
    • load Config/Constants.php
    • load Common.php
    • load Autoloader
    • load Services
    • Services::autoloader()
      • instantiate Autoloader
      • initialize()
        • load Composer autoloader
      • register()
    • autoload helpers
      • instantiate FileLocator
      • load URL helper
instantiate DotEnv
  • load .env file
define Environment
Services::codeigniter()
  • instantiate Config\App
  • instantiate CodeIgniter
initialize CodeIgniter
  • CodeIgniter::initialize()
    • load Environment bootstrap
    • Services::exceptions()
      • initialize()
        • set Exception/Error handler
    • check missing required PHP extensions
    • set default locale (Locale::setDefault())
    • set default timezone
    • initialize Kint
  • CodeIgniter::setContext()
CodeIgniter::run()
  • Services::createRequest()
    • Services::incomingrequest()
      • Services::uri()
        • Services::siteurifactory()
          • instantiate SiteURIFactory
        • SiteURIFactory::createFromGlobals()
          • detectRoutePath()
            • update superglobals
              • update $_SERVER
              • update $_GET
          • instantiate SiteURI
      • instantiate UserAgent
      • instantiate Request
        • IncomingRequest::__construct()
          • detectLocale()
            • if $negotiateLocale is true
              • get lang from content negotiation
              • setLocale()
                • set locale in Request
                • set default locale (Locale::setDefault())
  • instantiate Response
  • spoof request method
  • CodeIgniter::handleRequest()
    • force secure access
    • Event pre_system
    • check Page Cache
    • tryToRouteIt()
      • instantiate Route
      • instantiate Route
      • get Controller and method nam
      • get locale from rout
        • if route contains local
          • Request::setLocale(
            • set locale in Reques
            • set default locale (Locale::setDefault()
      • get Route Filters Info
    • instantiate Filters
    • enable Controller Filters
    • run before Filters
    • run Controller
      • run Closure controller
      • or
        • instantiate Controller
        • Event post_controller_constructor
        • run Controller method
    • gather output
    • run after Filters
    • Event post_system
    • return Response object
  • send response

関連

Tags: codeigniter, codeigniter4

PHPのJWTライブラリについて調べてみた

調査対象

  • firebase/php-jwt
  • lcobucci/jwt
  • web-token/jwt-framework
  • kelvinmo/simplejwt
  • sop/jwx

調査結果

firebase/php-jwt

https://packagist.org/packages/firebase/php-jwt

最新バージョン: v6.4.0 2023-02-09 21:01 UTC

php: ^7.1||^8.0

JWS: ○ JWE: × JWK: ○

サンプルコード
JWS HS256
$key = 'example_key';
$payload = [
    'iss' => 'http://example.org',
    'aud' => 'http://example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt = JWT::encode($payload, $key, 'HS256');

$decoded = JWT::decode($jwt, new Key($key, 'HS256'));
サンプルコード
JWS RS256
$privateKey = <<<EOD
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAuzWHNM5f+amCjQztc5QTfJfzCC5J4nuW+L/aOxZ4f8J3Frew
M2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJhzkPYLae7bTVro3hok0zDITR8F6S
JGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548tu4czCuqU8BGVOlnp6IqBHhAswNMM
78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vSopcT51koWOgiTf3C7nJUoMWZHZI5
HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTzTTqo1SCSH2pooJl9O8at6kkRYsrZ
WwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/BwQIDAQABAoIBAFtGaOqNKGwggn9k
6yzr6GhZ6Wt2rh1Xpq8XUz514UBhPxD7dFRLpbzCrLVpzY80LbmVGJ9+1pJozyWc
VKeCeUdNwbqkr240Oe7GTFmGjDoxU+5/HX/SJYPpC8JZ9oqgEA87iz+WQX9hVoP2
oF6EB4ckDvXmk8FMwVZW2l2/kd5mrEVbDaXKxhvUDf52iVD+sGIlTif7mBgR99/b
c3qiCnxCMmfYUnT2eh7Vv2LhCR/G9S6C3R4lA71rEyiU3KgsGfg0d82/XWXbegJW
h3QbWNtQLxTuIvLq5aAryV3PfaHlPgdgK0ft6ocU2de2FagFka3nfVEyC7IUsNTK
bq6nhAECgYEA7d/0DPOIaItl/8BWKyCuAHMss47j0wlGbBSHdJIiS55akMvnAG0M
39y22Qqfzh1at9kBFeYeFIIU82ZLF3xOcE3z6pJZ4Dyvx4BYdXH77odo9uVK9s1l
3T3BlMcqd1hvZLMS7dviyH79jZo4CXSHiKzc7pQ2YfK5eKxKqONeXuECgYEAyXlG
vonaus/YTb1IBei9HwaccnQ/1HRn6MvfDjb7JJDIBhNClGPt6xRlzBbSZ73c2QEC
6Fu9h36K/HZ2qcLd2bXiNyhIV7b6tVKk+0Psoj0dL9EbhsD1OsmE1nTPyAc9XZbb
OPYxy+dpBCUA8/1U9+uiFoCa7mIbWcSQ+39gHuECgYAz82pQfct30aH4JiBrkNqP
nJfRq05UY70uk5k1u0ikLTRoVS/hJu/d4E1Kv4hBMqYCavFSwAwnvHUo51lVCr/y
xQOVYlsgnwBg2MX4+GjmIkqpSVCC8D7j/73MaWb746OIYZervQ8dbKahi2HbpsiG
8AHcVSA/agxZr38qvWV54QKBgCD5TlDE8x18AuTGQ9FjxAAd7uD0kbXNz2vUYg9L
hFL5tyL3aAAtUrUUw4xhd9IuysRhW/53dU+FsG2dXdJu6CxHjlyEpUJl2iZu/j15
YnMzGWHIEX8+eWRDsw/+Ujtko/B7TinGcWPz3cYl4EAOiCeDUyXnqnO1btCEUU44
DJ1BAoGBAJuPD27ErTSVtId90+M4zFPNibFP50KprVdc8CR37BE7r8vuGgNYXmnI
RLnGP9p3pVgFCktORuYS2J/6t84I3+A17nEoB4xvhTLeAinAW/uTQOUmNicOP4Ek
2MsLL2kHgL8bLTmvXV4FX+PXphrDKg1XxzOYn0otuoqdAQrkK4og
-----END RSA PRIVATE KEY-----
EOD;

$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzWHNM5f+amCjQztc5QT
fJfzCC5J4nuW+L/aOxZ4f8J3FrewM2c/dufrnmedsApb0By7WhaHlcqCh/ScAPyJ
hzkPYLae7bTVro3hok0zDITR8F6SJGL42JAEUk+ILkPI+DONM0+3vzk6Kvfe548t
u4czCuqU8BGVOlnp6IqBHhAswNMM78pos/2z0CjPM4tbeXqSTTbNkXRboxjU29vS
opcT51koWOgiTf3C7nJUoMWZHZI5HqnIhPAG9yv8HAgNk6CMk2CadVHDo4IxjxTz
TTqo1SCSH2pooJl9O8at6kkRYsrZWwsKlOFE2LUce7ObnXsYihStBUDoeBQlGG/B
wQIDAQAB
-----END PUBLIC KEY-----
EOD;

$payload = [
    'iss' => 'example.org',
    'aud' => 'example.com',
    'iat' => 1356999524,
    'nbf' => 1357000000
];

$jwt = JWT::encode($payload, $privateKey, 'RS256');

$decoded = JWT::decode($jwt, new Key($publicKey, 'RS256'));
ソースサイズ
$ phploc src/
phploc 7.0.2 by Sebastian Bergmann.

Size
  Lines of Code (LOC)                             1308
  Comment Lines of Code (CLOC)                     415 (31.73%)
  Non-Comment Lines of Code (NCLOC)                893 (68.27%)
  Logical Lines of Code (LLOC)                     277 (21.18%)
    Classes                                        277 (100.00%)
      Average Class Length                          39
        Minimum Class Length                         0
        Maximum Class Length                       140
      Average Method Length                          6
        Minimum Method Length                        1
        Maximum Method Length                       22
      Average Methods Per Class                      5
        Minimum Methods Per Class                    0
        Maximum Methods Per Class                   16
    Functions                                        0 (0.00%)
      Average Function Length                        0
    Not in classes or functions                      0 (0.00%)

Cyclomatic Complexity
  Average Complexity per LLOC                     0.46
  Average Complexity per Class                   19.14
    Minimum Class Complexity                      1.00
    Maximum Class Complexity                     74.00
  Average Complexity per Method                   4.53
    Minimum Method Complexity                     1.00
    Maximum Method Complexity                    20.00

Dependencies
  Global Accesses                                    0
    Global Constants                                 0 (0.00%)
    Global Variables                                 0 (0.00%)
    Super-Global Variables                           0 (0.00%)
  Attribute Accesses                                73
    Non-Static                                      63 (86.30%)
    Static                                          10 (13.70%)
  Method Calls                                      77
    Non-Static                                      27 (35.06%)
    Static                                          50 (64.94%)

Structure
  Namespaces                                         1
  Interfaces                                         0
  Traits                                             0
  Classes                                            7
    Abstract Classes                                 0 (0.00%)
    Concrete Classes                                 7 (100.00%)
      Final Classes                                  0 (0.00%)
      Non-Final Classes                              7 (100.00%)
  Methods                                           36
    Scope
      Non-Static Methods                            13 (36.11%)
      Static Methods                                23 (63.89%)
    Visibility
      Public Methods                                18 (50.00%)
      Protected Methods                              0 (0.00%)
      Private Methods                               18 (50.00%)
  Functions                                          0
    Named Functions                                  0 (0.00%)
    Anonymous Functions                              0 (0.00%)
  Constants                                          8
    Global Constants                                 0 (0.00%)
    Class Constants                                  8 (100.00%)
      Public Constants                               0 (0.00%)
      Non-Public Constants                           8 (100.00%)

lcobucci/jwt

https://packagist.org/packages/lcobucci/jwt

最新バージョン: 5.0.0 2023-02-25 21:35 UTC

php: ~8.1.0 || ~8.2.0

JWS: ○ JWE: × JWK: ×

サンプルコード
JWS
$key = InMemory::base64Encoded(
    'hiG8DlOKvtih6AxlZn5XKImZ06yu8I3mkOzaJrEuW8yAv8Jnkw330uMt8AEqQ5LB'
);

$token = (new JwtFacade())->issue(
    new Sha256(),
    $key,
    static fn (
        Builder $builder,
        DateTimeImmutable $issuedAt
    ): Builder => $builder
        ->issuedBy('https://api.my-awesome-app.io')
        ->permittedFor('https://client-app.io')
        ->expiresAt($issuedAt->modify('+10 minutes'))
);

$jwt = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2NTg2OTYwNTIsIm5iZiI6MT'
    . 'Y1ODY5NjA1MiwiZXhwIjoxNjU4Njk2NjUyLCJpc3MiOiJodHRwczovL2FwaS5teS1hd2Vzb'
    . '21lLWFwcC5pbyIsImF1ZCI6Imh0dHBzOi8vY2xpZW50LWFwcC5pbyJ9.yzxpjyq8lXqMgaN'
    . 'rMEOLUr7R0brvhwXx0gp56uWEIfc';

$token = (new JwtFacade())->parse(
    $jwt,
    new Constraint\SignedWith(new Sha256(), $key),
    new Constraint\StrictValidAt(
        new FrozenClock(new DateTimeImmutable('2022-07-24 20:55:10+00:00'))
    )
);
ソースサイズ
$ phploc src
phploc 7.0.2 by Sebastian Bergmann.

Directories                                          9
Files                                               69

Size
  Lines of Code (LOC)                             2977
  Comment Lines of Code (CLOC)                     438 (14.71%)
  Non-Comment Lines of Code (NCLOC)               2539 (85.29%)
  Logical Lines of Code (LLOC)                     419 (14.07%)
    Classes                                        419 (100.00%)
      Average Class Length                           6
        Minimum Class Length                         0
        Maximum Class Length                        41
      Average Method Length                          1
        Minimum Method Length                        0
        Maximum Method Length                       12
      Average Methods Per Class                      3
        Minimum Methods Per Class                    0
        Maximum Methods Per Class                   14
    Functions                                        0 (0.00%)
      Average Function Length                        0
    Not in classes or functions                      0 (0.00%)

Cyclomatic Complexity
  Average Complexity per LLOC                     0.24
  Average Complexity per Class                    2.46
    Minimum Class Complexity                      1.00
    Maximum Class Complexity                     16.00
  Average Complexity per Method                   1.52
    Minimum Method Complexity                     1.00
    Maximum Method Complexity                     5.00

Dependencies
  Global Accesses                                    0
    Global Constants                                 0 (0.00%)
    Global Variables                                 0 (0.00%)
    Super-Global Variables                           0 (0.00%)
  Attribute Accesses                                86
    Non-Static                                      86 (100.00%)
    Static                                           0 (0.00%)
  Method Calls                                     220
    Non-Static                                     141 (64.09%)
    Static                                          79 (35.91%)

Structure
  Namespaces                                        10
  Interfaces                                        16
  Traits                                             0
  Classes                                           53
    Abstract Classes                                 4 (7.55%)
    Concrete Classes                                49 (92.45%)
      Final Classes                                 49 (100.00%)
      Non-Final Classes                              0 (0.00%)
  Methods                                          238
    Scope
      Non-Static Methods                           196 (82.35%)
      Static Methods                                42 (17.65%)
    Visibility
      Public Methods                               201 (84.45%)
      Protected Methods                              5 (2.10%)
      Private Methods                               32 (13.45%)
  Functions                                          3
    Named Functions                                  0 (0.00%)
    Anonymous Functions                              3 (100.00%)
  Constants                                         42
    Global Constants                                 0 (0.00%)
    Class Constants                                 42 (100.00%)
      Public Constants                              30 (71.43%)
      Non-Public Constants                          12 (28.57%)

web-token/jwt-framework

https://packagist.org/packages/web-token/jwt-framework

最新バージョン: 3.1.7 2023-03-11 14:35 UTC

php: >=8.1

JWS: ○ JWE: ○ JWK: ○

サンプルコード
JWS HS256
// The algorithm manager with the HS256 algorithm.
$algorithmManager = new AlgorithmManager([
    new HS256(),
]);

// Our key.
$jwk = new JWK([
    'kty' => 'oct',
    'k' => 'dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g',
]);

// We instantiate our JWS Builder.
$jwsBuilder = new JWSBuilder($algorithmManager);

// The payload we want to sign. The payload MUST be a string hence we use our JSON Converter.
$payload = json_encode([
    'iat' => time(),
    'nbf' => time(),
    'exp' => time() + 3600,
    'iss' => 'My service',
    'aud' => 'Your application',
]);

$jws = $jwsBuilder
    ->create()                               // We want to create a new JWS
    ->withPayload($payload)                  // We set the payload
    ->addSignature($jwk, ['alg' => 'HS256']) // We add a signature with a simple protected header
    ->build();                               // We build it
// The algorithm manager with the HS256 algorithm.
$algorithmManager = new AlgorithmManager([
    new HS256(),
]);

// We instantiate our JWS Verifier.
$jwsVerifier = new JWSVerifier(
    $algorithmManager
);

// Our key.
$jwk = new JWK([
    'kty' => 'oct',
    'k' => 'dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g',
]);

// The serializer manager. We only use the JWS Compact Serialization Mode.
$serializerManager = new JWSSerializerManager([
    new CompactSerializer(),
]);

// The input we want to check
$token = 'eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDc4OTY5OTIsIm5iZiI6MTUwNzg5Njk5MiwiZXhwIjoxNTA3OTAwNTkyLCJpc3MiOiJNeSBzZXJ2aWNlIiwiYXVkIjoiWW91ciBhcHBsaWNhdGlvbiJ9.eycp9PTdgO4WA-68-AMoHPwsKDr68NhjIQKz4lUkiI0';

// We try to load the token.
$jws = $serializerManager->unserialize($token);

// We verify the signature. This method does NOT check the header.
// The arguments are:
// - The JWS object,
// - The key,
// - The index of the signature to check. See 
$isVerified = $jwsVerifier->verifyWithKey($jws, $jwk, 0);
JWE
// The key encryption algorithm manager with the A256KW algorithm.
$keyEncryptionAlgorithmManager = new AlgorithmManager([
    new A256KW(),
]);

// The content encryption algorithm manager with the A256CBC-HS256 algorithm.
$contentEncryptionAlgorithmManager = new AlgorithmManager([
    new A256CBCHS512(),
]);

// The compression method manager with the DEF (Deflate) method.
$compressionMethodManager = new CompressionMethodManager([
    new Deflate(),
]);

// We instantiate our JWE Builder.
$jweBuilder = new JWEBuilder(
    $keyEncryptionAlgorithmManager,
    $contentEncryptionAlgorithmManager,
    $compressionMethodManager
);

// Our key.
$jwk = new JWK([
    'kty' => 'oct',
    'k' => 'dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g',
]);

// The payload we want to encrypt. It MUST be a string.
$payload = json_encode([
    'iat' => time(),
    'nbf' => time(),
    'exp' => time() + 3600,
    'iss' => 'My service',
    'aud' => 'Your application',
]);

$jwe = $jweBuilder
    ->create()              // We want to create a new JWE
    ->withPayload($payload) // We set the payload
    ->withSharedProtectedHeader([
        'alg' => 'A256KW',        // Key Encryption Algorithm
        'enc' => 'A256CBC-HS512', // Content Encryption Algorithm
        'zip' => 'DEF'            // We enable the compression (irrelevant as the payload is small, just for the example).
    ])
    ->addRecipient($jwk)    // We add a recipient (a shared key or public key).
    ->build();              // We build it
// The key encryption algorithm manager with the A256KW algorithm.
$keyEncryptionAlgorithmManager = new AlgorithmManager([
    new A256KW(),
]);

// The content encryption algorithm manager with the A256CBC-HS256 algorithm.
$contentEncryptionAlgorithmManager = new AlgorithmManager([
    new A256CBCHS512(),
]);

// The compression method manager with the DEF (Deflate) method.
$compressionMethodManager = new CompressionMethodManager([
    new Deflate(),
]);

// We instantiate our JWE Decrypter.
$jweDecrypter = new JWEDecrypter(
    $keyEncryptionAlgorithmManager,
    $contentEncryptionAlgorithmManager,
    $compressionMethodManager
);

// Our key.
$jwk = JWK::create([
    'kty' => 'oct',
    'k' => 'dzI6nbW4OcNF-AtfxGAmuyz7IpHRudBI0WgGjZWgaRJt6prBn3DARXgUR8NVwKhfL43QBIU2Un3AvCGCHRgY4TbEqhOi8-i98xxmCggNjde4oaW6wkJ2NgM3Ss9SOX9zS3lcVzdCMdum-RwVJ301kbin4UtGztuzJBeg5oVN00MGxjC2xWwyI0tgXVs-zJs5WlafCuGfX1HrVkIf5bvpE0MQCSjdJpSeVao6-RSTYDajZf7T88a2eVjeW31mMAg-jzAWfUrii61T_bYPJFOXW8kkRWoa1InLRdG6bKB9wQs9-VdXZP60Q4Yuj_WZ-lO7qV9AEFrUkkjpaDgZT86w2g',
]);

// The serializer manager. We only use the JWE Compact Serialization Mode.
$serializerManager = new JWESerializerManager([
    new CompactSerializer(),
]);

// The input we want to decrypt
$token = 'eyJhbGciOiJBMjU2S1ciLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiemlwIjoiREVGIn0.9RLpf3Gauf05QPNCMzPcH4XNBLmH0s3e-YWwOe57MTG844gnc-g2ywfXt_R0Q9qsR6WhkmQEhdLk2CBvfqr4ob4jFlvJK0yW.CCvfoTKO9tQlzCvbAuFAJg.PxrDlsbSRcxC5SuEJ84i9E9_R3tCyDQsEPTIllSCVxVcHiPOC2EdDlvUwYvznirYP6KMTdKMgLqxB4BwI3CWtys0fceSNxrEIu_uv1WhzJg.4DnyeLEAfB4I8Eq0UobnP8ymlX1UIfSSADaJCXr3RlU';

// We try to load the token.
$jwe = $serializerManager->unserialize($token);

// We decrypt the token. This method does NOT check the header.
$success = $jweDecrypter->decryptUsingKey($jwe, $jwk, 0);
ソースサイズ
$ phploc src
phploc 7.0.2 by Sebastian Bergmann.

Directories                                         59
Files                                              375

Size
  Lines of Code (LOC)                            22879
  Comment Lines of Code (CLOC)                    2497 (10.91%)
  Non-Comment Lines of Code (NCLOC)              20382 (89.09%)
  Logical Lines of Code (LLOC)                    3943 (17.23%)
    Classes                                       3722 (94.40%)
      Average Class Length                          10
        Minimum Class Length                         0
        Maximum Class Length                       145
      Average Method Length                          2
        Minimum Method Length                        0
        Maximum Method Length                       31
      Average Methods Per Class                      4
        Minimum Methods Per Class                    0
        Maximum Methods Per Class                   29
    Functions                                      221 (5.60%)
      Average Function Length                        5
    Not in classes or functions                      0 (0.00%)

Cyclomatic Complexity
  Average Complexity per LLOC                     0.33
  Average Complexity per Class                    4.79
    Minimum Class Complexity                      1.00
    Maximum Class Complexity                     65.00
  Average Complexity per Method                   1.96
    Minimum Method Complexity                     1.00
    Maximum Method Complexity                    14.00

Dependencies
  Global Accesses                                    0
    Global Constants                                 0 (0.00%)
    Global Variables                                 0 (0.00%)
    Super-Global Variables                           0 (0.00%)
  Attribute Accesses                               719
    Non-Static                                     719 (100.00%)
    Static                                           0 (0.00%)
  Method Calls                                    3377
    Non-Static                                    2807 (83.12%)
    Static                                         570 (16.88%)

Structure
  Namespaces                                        41
  Interfaces                                        25
  Traits                                             0
  Classes                                          315
    Abstract Classes                                25 (7.94%)
    Concrete Classes                               290 (92.06%)
      Final Classes                                203 (70.00%)
      Non-Final Classes                             87 (30.00%)
  Methods                                         1399
    Scope
      Non-Static Methods                          1248 (89.21%)
      Static Methods                               151 (10.79%)
    Visibility
      Public Methods                              1001 (71.55%)
      Protected Methods                            194 (13.87%)
      Private Methods                              204 (14.58%)
  Functions                                         40
    Named Functions                                  0 (0.00%)
    Anonymous Functions                             40 (100.00%)
  Constants                                         64
    Global Constants                                 0 (0.00%)
    Class Constants                                 64 (100.00%)
      Public Constants                              49 (76.56%)
      Non-Public Constants                          15 (23.44%)

kelvinmo/simplejwt

https://packagist.org/packages/kelvinmo/simplejwt

最新バージョン: v0.7.0 2022-11-25 21:25 UTC

php: ^7.1 || ^8.0

JWS: ○ JWE: ○ JWK: ○

サンプルコード
JWS HS256
$set = new SimpleJWT\Keys\KeySet();
$key = new SimpleJWT\Keys\SymmetricKey('secret123', 'bin');
$set->add($key);

// Note $headers['alg'] is required
$headers = ['alg' => 'HS256', 'typ' => 'JWT'];
$claims = ['iss' => 'me', 'exp' => 1234567];
$jwt = new SimpleJWT\JWT($headers, $claims);

try {
    print $jwt->encode($set);
} catch (\RuntimeException $e) {

}

try {
    $jwt = SimpleJWT\JWT::decode('abc.def.ghigjghr', $set, 'HS256');
} catch (SimpleJWT\InvalidTokenException $e) {

}
JWE
// Note $headers['alg'] and $headers['enc'] are required
$headers = ['alg' => 'PBES2-HS256+A128KW', 'enc' => 'A128CBC-HS256'];
$plaintext = 'This is the plaintext I want to encrypt.';
$jwt = new SimpleJWT\JWE($headers, $plaintext);

try {
    print $jwt->encrypt($set);
} catch (\RuntimeException $e) {

}

try {
    $jwt = SimpleJWT\JWE::decrypt('abc.def.ghi.klm.nop', $set, 'PBES2-HS256+A128KW');
} catch (SimpleJWT\InvalidTokenException $e) {

}

print $jwt->getHeader('alg');
print $jwt->getPlaintext();
ソースサイズ
$ phploc src
phploc 7.0.2 by Sebastian Bergmann.

Directories                                          7
Files                                               38

Size
  Lines of Code (LOC)                             6467
  Comment Lines of Code (CLOC)                    2987 (46.19%)
  Non-Comment Lines of Code (NCLOC)               3480 (53.81%)
  Logical Lines of Code (LLOC)                    1273 (19.68%)
    Classes                                       1273 (100.00%)
      Average Class Length                          33
        Minimum Class Length                         0
        Maximum Class Length                       129
      Average Method Length                          5
        Minimum Method Length                        1
        Maximum Method Length                       74
      Average Methods Per Class                      6
        Minimum Methods Per Class                    0
        Maximum Methods Per Class                   18
    Functions                                        0 (0.00%)
      Average Function Length                        0
    Not in classes or functions                      0 (0.00%)

Cyclomatic Complexity
  Average Complexity per LLOC                     0.41
  Average Complexity per Class                   14.68
    Minimum Class Complexity                      1.00
    Maximum Class Complexity                     63.00
  Average Complexity per Method                   3.37
    Minimum Method Complexity                     1.00
    Maximum Method Complexity                    40.00

Dependencies
  Global Accesses                                    0
    Global Constants                                 0 (0.00%)
    Global Variables                                 0 (0.00%)
    Super-Global Variables                           0 (0.00%)
  Attribute Accesses                               256
    Non-Static                                     210 (82.03%)
    Static                                          46 (17.97%)
  Method Calls                                     494
    Non-Static                                     314 (63.56%)
    Static                                         180 (36.44%)

Structure
  Namespaces                                         8
  Interfaces                                         5
  Traits                                             1
  Classes                                           32
    Abstract Classes                                 4 (12.50%)
    Concrete Classes                                28 (87.50%)
      Final Classes                                  0 (0.00%)
      Non-Final Classes                             28 (100.00%)
  Methods                                          229
    Scope
      Non-Static Methods                           197 (86.03%)
      Static Methods                                32 (13.97%)
    Visibility
      Public Methods                               191 (83.41%)
      Protected Methods                             32 (13.97%)
      Private Methods                                6 (2.62%)
  Functions                                          6
    Named Functions                                  0 (0.00%)
    Anonymous Functions                              6 (100.00%)
  Constants                                         38
    Global Constants                                 0 (0.00%)
    Class Constants                                 38 (100.00%)
      Public Constants                              38 (100.00%)
      Non-Public Constants                           0 (0.00%)

sop/jwx

https://packagist.org/packages/sop/jwx

最新バージョン: 0.11.1 2021-09-27 06:57 UTC

php: >=7.2

JWS: ○ JWE: ○ JWK: ○

コメント

https://github.com/sop/jwx/issues/2 に脆弱性があるという報告があるが、脆弱性の内容と修正済みかどうかは公表されていませんでした。その後、0.12.0 で修正されました。

サンプルコード
JWS HS256
// compose claims set
$claims = new Claims(
    new IssuerClaim('John Doe'),
    new SubjectClaim('Jane Doe'),
    new AudienceClaim('acme-client'),
    IssuedAtClaim::now(),
    NotBeforeClaim::now(),
    ExpirationTimeClaim::fromString('now + 30 minutes'),
    new JWTIDClaim(UUIDv4::createRandom()->canonical()),
    new Claim('custom claim', ['any', 'values']));
// create a signed JWT using HS256 with "secret" as a password
$jwt = JWT::signedFromClaims($claims, new HS256Algorithm('secret'));
echo $jwt->token() . "\n";

// read JWT token from the first argument
$jwt = new JWT($argv[1]);
// key to use for signature validation
$jwk = SymmetricKeyJWK::fromKey('secret');
// create validation context
$ctx = ValidationContext::fromJWK($jwk)
    ->withIssuer('John Doe')
    ->withSubject('Jane Doe')
    ->withAudience('acme-client');
// get claims set from the JWT. signature shall be verified and claims
// validated according to validation context.
$claims = $jwt->claims($ctx);
// print all claims
foreach ($claims as $claim) {
    printf("%s: %s\n", $claim->name(), json_encode($claim->value()));
}
JWE
// compose claims set
$claims = new Claims(
    new Claim('secret data', 'for your eyes only'),
    IssuedAtClaim::now(),
    NotBeforeClaim::now(),
    ExpirationTimeClaim::fromString('now + 30 minutes'));
// load RSA public key
$jwk = RSAPublicKeyJWK::fromPEM(
    PEM::fromFile(dirname(__DIR__) . '/test/assets/rsa/public_key.pem'));
$key_algo = RSAESPKCS1Algorithm::fromPublicKey($jwk);
$enc_algo = new A128CBCHS256Algorithm();
// create an encrypted JWT token
$jwt = JWT::encryptedFromClaims($claims, $key_algo, $enc_algo);
echo $jwt->token() . "\n";

// read JWT token from the first argument
$jwt = new JWT($argv[1]);
// load RSA private key
$jwk = RSAPrivateKeyJWK::fromPEM(
    PEM::fromFile(dirname(__DIR__) . '/test/assets/rsa/private_key.pem'));
// create validation context containing only key for decryption
$ctx = ValidationContext::fromJWK($jwk)
    // NOTE: asymmetric key derivation algorithms are not enabled by default
    // due to sign/encrypt confusion vulnerability!
    ->withPermittedAlgorithmsAdded(JWA::ALGO_RSA1_5);
// decrypt claims from the encrypted JWT
$claims = $jwt->claims($ctx);
// print all claims
foreach ($claims as $claim) {
    printf("%s: %s\n", $claim->name(), json_encode($claim->value()));
}
ソースサイズ
$ phploc lib
phploc 7.0.2 by Sebastian Bergmann.

Directories                                         24
Files                                              145

Size
  Lines of Code (LOC)                            10643
  Comment Lines of Code (CLOC)                    4253 (39.96%)
  Non-Comment Lines of Code (NCLOC)               6390 (60.04%)
  Logical Lines of Code (LLOC)                    1387 (13.03%)
    Classes                                       1387 (100.00%)
      Average Class Length                           9
        Minimum Class Length                         0
        Maximum Class Length                        71
      Average Method Length                          1
        Minimum Method Length                        1
        Maximum Method Length                       10
      Average Methods Per Class                      4
        Minimum Methods Per Class                    0
        Maximum Methods Per Class                   49
    Functions                                        0 (0.00%)
      Average Function Length                        0
    Not in classes or functions                      0 (0.00%)

Cyclomatic Complexity
  Average Complexity per LLOC                     0.19
  Average Complexity per Class                    2.84
    Minimum Class Complexity                      1.00
    Maximum Class Complexity                     32.00
  Average Complexity per Method                   1.46
    Minimum Method Complexity                     1.00
    Maximum Method Complexity                     9.00

Dependencies
  Global Accesses                                    0
    Global Constants                                 0 (0.00%)
    Global Variables                                 0 (0.00%)
    Super-Global Variables                           0 (0.00%)
  Attribute Accesses                               229
    Non-Static                                     229 (100.00%)
    Static                                           0 (0.00%)
  Method Calls                                     846
    Non-Static                                     552 (65.25%)
    Static                                         294 (34.75%)

Structure
  Namespaces                                        25
  Interfaces                                         6
  Traits                                            10
  Classes                                          129
    Abstract Classes                                21 (16.28%)
    Concrete Classes                               108 (83.72%)
      Final Classes                                  0 (0.00%)
      Non-Final Classes                            108 (100.00%)
  Methods                                          617
    Scope
      Non-Static Methods                           519 (84.12%)
      Static Methods                                98 (15.88%)
    Visibility
      Public Methods                               504 (81.69%)
      Protected Methods                             98 (15.88%)
      Private Methods                               15 (2.43%)
  Functions                                          2
    Named Functions                                  0 (0.00%)
    Anonymous Functions                              2 (100.00%)
  Constants                                        201
    Global Constants                                 0 (0.00%)
    Class Constants                                201 (100.00%)
      Public Constants                             201 (100.00%)
      Non-Public Constants                           0 (0.00%)

参考

Tags: php, jwt