14

Décodez un signmii

Encoder un signmii consiste à fabriquer un marquage en concaténant un SHA1 en hexadécimal de 20 octets, un horodatage GMT de 4 octets et un numéro de série de 8 octets, à calculer le SHA1 de ce marquage en hexadécimal, à concaténer ce SHA1 avec le marquage, et à chiffrer le tout avec la partie privée d'une clé RSA de 2048 octets. Le résultat fait 256 octets. Pour faciliter l'affichage et le transport d'un signmii, ces 256 octets sont ensuite encodés en BASE64 puis filtrés pour remplacer les caractères + (PLUS) et / (BARRE OBLIQUE) du format BASE64 par les caractères - (TIRET) et _ (SOULIGNÉ) compatibles avec le format d'une URL. Un signmii fait 342 octets.

Téléchargez le certificat signmiikey.crt contenant la clé publique qui vous permettra de décoder un signmii.

L'empreinte du certificat est :

13:B0:CD:83:00:EB:B8:4A:68:BB:C5:BE:31:84:82:8E:97:14:69:6E

Vous pouvez la contrôler avec la commande openssl :

$ openssl x509 -in signmiikey.crt -fingerprint -noout
SHA1 Fingerprint=13:B0:CD:83:00:EB:B8:4A:68:BB:C5:BE:31:84:82:8E:97:14:69:6E

Téléchargez le script checksignmii.php qui contient le programme en PHP que vous exécuterez pour décoder un signmii avec le certificat signmiikey.crt.

Le script checksignmii.php lit un fichier qui contient un signmii, le décode avec la clé publique incluse dans le fichier signmiikey.crt et affiche le SHA1, l'horodatage et le numéro de série chiffrés dans le signmii.

  1. define('USAGE', 'php -f %s signmiifile [certfile]');

La constante USAGE définit le bon usage de la commande.

  1. $certfile='signmiikey.crt';

Initialise $certfile avec le nom du fichier contenant le certificat avec la clé publique.

  1. function abort($msg, $code=1) {
  2.     echo $msg, PHP_EOL;
  3.     exit($code);
  4. }

La fonction abort affiche $msg et quitte le programme en retournant le code d'erreur $code.

  1. function usage() {
  2.     global $argv;
  3.  
  4.     abort(sprintf(USAGE, basename($argv[0])), 1);
  5. }

La fonction usage quitte le programme en affichant l'usage de la commande. Le nom du programme remplace le %s de la constante USAGE.

  1. function urldecodebase64($s) {
  2.     $s64 = str_replace(array('-', '_' ), array('+', '/'), $s);
  3.  
  4.     $mod4 = strlen($s64) % 4;
  5.     if ($mod4) {
  6.         $s64 .= substr('====', $mod4);
  7.     }
  8.  
  9.     return base64_decode($s64);
  10. }

La fonction urldecodebase64 inverse l'encodage en BASE64 d'un série d'octets où les caractères + (PLUS) et / (BARRE OBLIQUE) du format BASE64 ont été remplacés par les caractères - (TIRET) et _ (SOULIGNÉ) compatibles avec le format d'une URL.

  1. if (!($argc == 2 or $argc == 3)) {
  2.     usage();
  3. }
  4.  
  5. $infile=$argv[1];
  6.  
  7. if ($argc == 3) {
  8.     $certfile=$argv[2];
  9. }

Vérifie le nombre d'arguments passés à la commande. Extrait le nom du fichier contenant le signmii et le nom du fichier du certificat avec la clé publique si la commande a 2 arguments.

  1. $lines=file($infile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
  2.  
  3. if (!$lines) {
  4.     abort('signmii?');
  5. }

Lit le fichier contenant le signmii. Quitte le programme si le fichier est vide.

  1. $s64='';
  2. foreach ($lines as $s) {
  3.     if ($s[0] != '#') {
  4.         $s64=$s;
  5.         break;
  6.     }
  7. }
  8.  
  9. if (strlen($s64) != 342) {
  10.     abort('signmii?');
  11. }

Saute les lignes de commentaires lues dans le fichier. Vérifie que le résultat fait 342 caractères.

  1. $crypto=urldecodebase64($s64);
  2.  
  3. if (strlen($crypto) != 256) {
  4.     abort('signmii?');
  5. }

Décode l'encodage en BASE64 avec la fonction urldecodebase64. Vérifie que le résultat fait 256 octets.

  1. $pem=@file_get_contents($certfile);
  2. if (!$pem) {
  3.     abort('certfile' . '?');
  4. }
  5. $key=openssl_pkey_get_public($pem);
  6. if (!$key) {
  7.     abort('certfile' . '?');
  8. }
  9.  
  10. $r=openssl_public_decrypt($crypto, $sdata, $key);
  11. if (!$r) {
  12.     abort('signmii' . '?');
  13. }

Lit le certificat et en extrait la clé publique. Décode le signmii au format binaire avec la clé publique.

  1. $digest=substr($sdata, 0, 20);
  2.  
  3. $data=substr($sdata, 20, 32);
  4.  
  5. if ($digest != sha1($data, true)) {
  6.     abort('signmii' . '?');
  7. }

Vérifie l'empreinte du signmii.

  1. $sha1bin=substr($data, 0, 20);
  2. $r=unpack('H*', $sha1bin);
  3. $sha1=$r[1];
  4.  
  5. $gmtbin=substr($data, 20, 4);
  6. $r=unpack('N', $gmtbin);
  7. $gmt=gmdate('Y-m-d\TH:i:s\Z', $r[1]);
  8.  
  9. $serialbin=substr($data, 20+4, 8);
  10. $r=unpack('H*', $serialbin);
  11. $serial=$r[1];

Extrait le SHA1, l'horodatage et le numéro de série contenus dans le signmii décodé.

  1. echo $sha1, ' ', $gmt, ' ', $serial, PHP_EOL;

Affiche le SHA1, l'horodatage et le numéro de série séparés par un espace.

EXEMPLE

# ed0847ae3231350b0153cd8b9c8f56b87ab37801 2014-05-19T21:36:11Z 0000000000000001

uIWPRlfPaB8VgkTHIg8IoTe72WtTLgL_vGoWjY8PfM9fFjwXb8LmvMsMGKVUUTvJOy-z536BC-GMCOaDDdHhcWqGEYyUlXULwwGBXQL7drGnnbTa0H4bCD1YME6H9q7xIdMqlD9pIS-CIAsAo1SYguOhHP9bBlZ_7vk91gmKmxJQi6ril_UlvUmvmjJbUSnoyvDBLPcOWTa0hPDiPKnLifaimHHzkKfLtD9Ck2DAam9G3q3ME0zayVOTTlFdyPsOwvM6SvOMqAi-iBV40Bg5Ky4wKJztDMiCCBCdx3k-jvMfVtZM61MoIDNaICeI59UYE-HL8cPX3CcRphXYdFmRHg

NOTE : Le fichier peut contenir des lignes de commentaires commençant par un # (DIÈSE) et des lignes vides.

Copiez les 3 fichiers signmiikey.crt, checksignmii.php et 1.signmii dans le même dossier. Exécutez le script checksignmii.php avec php en passant le nom du fichier contenant le signmii en argument :

$ php -f checksignmii.php 1.signmii
ed0847ae3231350b0153cd8b9c8f56b87ab37801 2014-05-19T21:36:11Z 0000000000000001

Vous pouvez ajouter le nom du fichier contenant le certificat à la ligne de commande :

$ php -f checksignmii.php 1.signmii signmiikey.crt
ed0847ae3231350b0153cd8b9c8f56b87ab37801 2014-05-19T21:36:11Z 0000000000000001

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].