commit 48a5360d0d6abe26c38f7f4394290eec4e865fcd Author: Raphael Dannecker Date: Tue Feb 25 16:10:55 2025 +0100 Initial commit diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..57e0048 --- /dev/null +++ b/.htaccess @@ -0,0 +1,6 @@ + + Order Allow,Deny + Deny from all + +RedirectMatch 404 /\.git +RedirectMatch 404 /keys diff --git a/README.md b/README.md new file mode 100644 index 0000000..130096c --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# StudentCard + +PHP application to create and verify a student card. + +## Install: + + git clone https://git.codeberg.org/digitalsouveraeneschule/studentcard.git + +## Create keys + + php genkey.php + +## Configure + + cd config + cp config.php.sample config.php + +edit config.php diff --git a/callback.php b/callback.php new file mode 100644 index 0000000..368c1b1 --- /dev/null +++ b/callback.php @@ -0,0 +1,30 @@ +setRedirectURL($CONFIG['baseurl'] . 'callback.php'); + +// get token +$oidc->authenticate(); + +// store user data in session +$_SESSION['id_token'] = $oidc->getIdToken(); +foreach ($CONFIG['oidc']['mappings'] as $key => $value) { + $_SESSION[$key] = $oidc->requestUserInfo($value); +} + +if (! $_SESSION['doe'] ) { + $_SESSION['doe'] = $CONFIG['default_doe']; +} + +// redirect to home +header('Location: card.php'); +?> diff --git a/card.php b/card.php new file mode 100644 index 0000000..ac2dfb5 --- /dev/null +++ b/card.php @@ -0,0 +1,91 @@ + $value) { + $data[$key] = $_SESSION[$key]; +} + +if ($CONFIG['version'] === '0.1') { + $data_json = json_encode($data); + $data_crypt = sodium_crypto_box_seal($data_json, sodium_crypto_sign_ed25519_pk_to_curve25519($public_key)); + $message['verify'] = 'ausweis.steinbeis.schule'; + $message['data'] = sodium_bin2base64($data_crypt, SODIUM_BASE64_VARIANT_URLSAFE); + $message['signature'] = sodium_bin2base64(sodium_crypto_sign_detached($message['verify'] . $message['data'], $private_key), SODIUM_BASE64_VARIANT_URLSAFE); + $message_encoded = urlencode(json_encode($message)); +} elseif ($CONFIG['version'] === '0.2') { + $data_json = json_encode($data); + $data_crypt = sodium_crypto_box_seal($data_json, sodium_crypto_sign_ed25519_pk_to_curve25519($public_key)); + $message_encoded = sodium_bin2base64(sodium_crypto_sign($data_crypt, $private_key), SODIUM_BASE64_VARIANT_URLSAFE); +} elseif ($CONFIG['version'] === '0.3') { + $nonce = random_bytes(SODIUM_CRYPTO_BOX_NONCEBYTES); + $keypair = sodium_crypto_box_keypair_from_secretkey_and_publickey( + sodium_crypto_sign_ed25519_sk_to_curve25519($private_key), + sodium_crypto_sign_ed25519_pk_to_curve25519($public_key)); + $data_json = json_encode($data); + $data_crypt = sodium_crypto_box($data_json, $nonce, $keypair); + $data_crypt = sodium_crypto_box_seal($data_json, sodium_crypto_sign_ed25519_pk_to_curve25519($public_key)); + $message_encoded = sodium_bin2base64(sodium_crypto_sign($data_crypt, $private_key), SODIUM_BASE64_VARIANT_URLSAFE); +} + +//echo $message_encoded . "\n Length:" . strlen($message_encoded); +//$message_encoded = urlencode(gzcompress(json_encode($message),9)); + +//echo "data_json: " . $data_json . "\n"; +//echo "data_crypt: " . $data_crypt . "\n"; +//echo "message: "; +//var_dump($message); +//echo "\n"; +/////// sodium_crypto_sign_ed25519_sk_to_curve25519($private_key) +//echo "Message: ".$message_encoded; + +$url = $CONFIG['baseurl'] . 'verify.php?v=' . $CONFIG['version'] . '&d=' . $message_encoded; + +// url is needed by qrcode.php +$_SESSION['url'] = $url; + +$verified = true; + +if (isset($_GET['pdf'])) { + $pdf=true; + ob_start(); + include('idcard-print.php'); + $out = ob_get_contents(); + ob_end_clean(); + $html2pdf = new Html2Pdf(orientation:'L', format:Array(96,65), margins:Array(5,5,5,0)); + //$html2pdf = new Html2Pdf(orientation:'L', format:'BUSINESS_CARD',margins:Array(0,0,0,0)); + $html2pdf->writeHTML($out); + $html2pdf->output('schuelerausweis.pdf','D'); +} else { + include('idcard.php'); +} + +?> diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..6e6b1c9 --- /dev/null +++ b/composer.json @@ -0,0 +1,7 @@ +{ + "require": { + "jumbojett/openid-connect-php": "^1.0", + "endroid/qr-code": "^6.0", + "spipu/html2pdf": "^5.3" + } +} diff --git a/config/config.php.sample b/config/config.php.sample new file mode 100644 index 0000000..d0ae71f --- /dev/null +++ b/config/config.php.sample @@ -0,0 +1,30 @@ + '0.2', + 'default_doe' => '31.07.2025', + 'baseurl' => 'https://ausweis.example.com/', + 'oidc' => array( + 'url' => 'https://idam.example.com/realms/schoolrealm/', + 'clientid' => 'ausweis', + 'secret' => 'secret', + 'mappings' => array( + 'firstname' => 'given_name', + 'lastname' => 'family_name', + 'birthdate' => 'birthdate', + 'id' => 'sophomorixUnid', + 'role' => 'sophomorixRole', + 'doe' => 'doe' + ) + ), + 'ldap' => array( + 'bind_user' => 'cn=global-binduser,OU=Management,OU=GLOBAL,DC=linuxmuster,DC=lan', + 'bind_passwd' => 'secret', + 'base_dn' => 'OU=default-school,OU=SCHOOLS,DC=linuxmuster,DC=lan', + 'url' => 'ldaps://server.example.com:636', + 'filter_id' => '(&(obdjectclass=person)(sophomorixUnid=%s)(!(sophomorixAdminClass=attic)))', + 'filter_name' => '(&(objectclass=person)(givenName=%s)(sn=%s)(sophomorixBirthdate=%s)(!(sophomorixAdminClass=attic)))' + ) +); + +?> diff --git a/genkey.php b/genkey.php new file mode 100755 index 0000000..e7cb2ae --- /dev/null +++ b/genkey.php @@ -0,0 +1,10 @@ + diff --git a/idcard-print.php b/idcard-print.php new file mode 100644 index 0000000..226a340 --- /dev/null +++ b/idcard-print.php @@ -0,0 +1,199 @@ + + + + + + Schülerausweis + + + +
+
+
Identity Card
+ +
+
+
+ Name
+
+
+
+ Date of Birth
+
+
+
+ Date of Expiry
+
+ +
+
+
+ Gewerbliche Schule I
+ Karlstraße 40
+ D-72764 Reutlingen
+ www.steinbeis.schule
+ info@steinbeis.schule
+ +49 7121 485 111 +
+ + + + + +
+
+ '; } ?> + '; } ?> + '; } ?> +
+
+
+ +
+ +
+
+
+
+
+ + diff --git a/idcard.php b/idcard.php new file mode 100644 index 0000000..39ce938 --- /dev/null +++ b/idcard.php @@ -0,0 +1,192 @@ + + + + + + Schülerausweis + + + +
+
+
+
+
Identity Card
+
+ +
+
+
+
+ + Name +
+
+ + Date of Birth +
+
+ + Date of Expiry +
+
Nur gültig mit amtlichem Lichtbildausweis
Only valid with official photo Identity Card
+
+
+
+ Gewerbliche Schule I
+ Karlstraße 40
+ D-72764 Reutlingen
+ www.steinbeis.schule
+ info@steinbeis.schule
+ +49 7121 485 111 +
+
+
+ '; + } elseif (isset($valid) && !$valid) { + echo 'ungültig'; + } elseif (isset($pdf)) { + echo ''; + } else { + echo 'QR Code'; + } + } else { + echo 'Signatur ist ungültig'; + } ?> +
+
+
+
'; + echo 'verify'; + } else { + } + } else { + echo 'Die Signatur ist ungültig'; + } ?> +
+
+ " . date('H:i:s'); ?> +
+
+
+
+
+
+ + diff --git a/img/checked.svg b/img/checked.svg new file mode 100644 index 0000000..ba52a94 --- /dev/null +++ b/img/checked.svg @@ -0,0 +1,333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/expired.svg b/img/expired.svg new file mode 100644 index 0000000..155da70 --- /dev/null +++ b/img/expired.svg @@ -0,0 +1,10 @@ + + + + + + EXPIRED + + + + diff --git a/img/fvs-background-print.png b/img/fvs-background-print.png new file mode 100644 index 0000000..fd4231a Binary files /dev/null and b/img/fvs-background-print.png differ diff --git a/img/fvs-background.png b/img/fvs-background.png new file mode 100644 index 0000000..e7fedd9 Binary files /dev/null and b/img/fvs-background.png differ diff --git a/img/fvs-background.svg b/img/fvs-background.svg new file mode 100644 index 0000000..ae8b41e --- /dev/null +++ b/img/fvs-background.svg @@ -0,0 +1,92 @@ + + diff --git a/img/logo-fvs.png b/img/logo-fvs.png new file mode 100644 index 0000000..49aa9b3 Binary files /dev/null and b/img/logo-fvs.png differ diff --git a/img/logo-fvs.svg b/img/logo-fvs.svg new file mode 100644 index 0000000..bba1040 --- /dev/null +++ b/img/logo-fvs.svg @@ -0,0 +1,359 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/pdf.svg b/img/pdf.svg new file mode 100644 index 0000000..666f219 --- /dev/null +++ b/img/pdf.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/img/signature_invalid.svg b/img/signature_invalid.svg new file mode 100644 index 0000000..170cc1f --- /dev/null +++ b/img/signature_invalid.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/index.php b/index.php new file mode 100644 index 0000000..ccffdee --- /dev/null +++ b/index.php @@ -0,0 +1,27 @@ +setRedirectURL($CONFIG['baseurl'] . 'callback.php'); + +// check if user is logged in +if (isset($_SESSION['id_token'])) { + header('Location: card.php'); + /*echo "Willkommen,"; + echo '
Ausweis anzeigen'; + echo '
Ausweis download (pdf)'; + echo '
Abmelden';*/ +} else { + // redirect to keycloak login + $oidc->authenticate(); +} + +?> diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..cd9f82a --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ + diff --git a/qrcode.php b/qrcode.php new file mode 100644 index 0000000..8d2bebf --- /dev/null +++ b/qrcode.php @@ -0,0 +1,51 @@ +setSize(300); // Größe des QR-Codes +//$qrCode->setMargin(0); // Rand um den QR-Code + +// generate QR-Code as png +$writer = new PngWriter(); +$result = $writer->write($qrCode); + +// set header +header('Content-Type: '.$result->getMimeType()); +header('Content-Disposition: inline; filename="qrcode.png"'); + +// output QR-Code +echo $result->getString(); +?> diff --git a/verify.php b/verify.php new file mode 100644 index 0000000..1179306 --- /dev/null +++ b/verify.php @@ -0,0 +1,81 @@ +