<?php
namespace nur\passwd;

use nur\b\IllegalAccessException;

/**
 * Class passwords; outils pour gérer les mots de passe
 */
class passwords {
  /** obtenir le salt d'un mot de passe hashé en CRYPT */
  static function get_des_crypt_salt(string $crypt): string {
    return substr($crypt, 0, 2);
  }

  static function des_crypt(string $clear, ?string $salt=null): string {
    if ($salt === null) $salt = "AA";
    return crypt($clear, $salt);
  }

  static function sha(string $clear): string {
    return base64_encode(sha1($clear, true));
  }

  static function xsha(string $clear): string {
    return strtoupper(sha1($clear));
  }

  /** obtenir le salt d'un mot de passe hashé en SSHA */
  static function get_ssha_salt(string $ssha): string {
    return substr(base64_decode($ssha), 20);
  }

  static function ssha(string $clear, ?string $salt=null): string {
    if ($salt === null) $salt = random_bytes(20);
    return base64_encode(sha1("$clear$salt", true).$salt);
  }

  static function ntlm(string $clear): string {
    $string = iconv("UTF-8", "UTF-16LE", $clear);
    return strtoupper(bin2hex(hash("md4", $string, true)));
  }

  private static function lm_des_encrypt(string $string) {
    $len = strlen($string);
    $tmp = [];
    for ($i = 0; $i < 7; $i++) {
      $tmp[] = $i < $len? ord($string[$i]): 0;
    }
    $key = [];
    $key[] = $tmp[0] & 254;
    $key[] = ($tmp[0] << 7) | ($tmp[1] >> 1);
    $key[] = ($tmp[1] << 6) | ($tmp[2] >> 2);
    $key[] = ($tmp[2] << 5) | ($tmp[3] >> 3);
    $key[] = ($tmp[3] << 4) | ($tmp[4] >> 4);
    $key[] = ($tmp[4] << 3) | ($tmp[5] >> 5);
    $key[] = ($tmp[5] << 2) | ($tmp[6] >> 6);
    $key[] = $tmp[6] << 1;

    $key0 = "";
    foreach ($key as $k) {
      $key0 .= chr($k);
    }
    $crypt = openssl_encrypt("KGS!@#$%", "des-ecb", $key0
      , OPENSSL_RAW_DATA + OPENSSL_ZERO_PADDING);

    return bin2hex($crypt);
  }

  static function lm(string $clear): string {
    $string = strtoupper(substr($clear,0,14));
    $part1 = self::lm_des_encrypt(substr($string, 0, 7));
    $part2 = self::lm_des_encrypt(substr($string, 7, 7));
    return strtoupper($part1.$part2);
  }

  private static $lsc_key;

  static function init_lsc(string $key): void {
    self::$lsc_key = hex2bin($key);
  }
  private static function lsc_key(): string {
    $lsc_key = self::$lsc_key;
    if ($lsc_key === null) {
      throw IllegalAccessException::unexpected_state("init_lsc");
    }
    return $lsc_key;
  }

  static function is_lsc_available(): bool {
    return self::$lsc_key !== null;
  }

  static function decrypt_lsc(string $lsc): string {
    return openssl_decrypt($lsc, "aes-128-ecb", self::lsc_key());
  }

  static function encrypt_lsc(string $clear): string {
    return openssl_encrypt($clear, "aes-128-ecb", self::lsc_key());
  }
}