<?php


namespace Lackoxygen\GzCbec\Utils;


use Lackoxygen\GzCbec\Exception\Exception;

class RSA
{
    /**
     * @param $key
     *
     * @return string
     */
    public static function trimKey($key): string
    {
        return wordwrap(preg_replace('/[\r\n]/', '', $key), 64, "\n", true);
    }

    /**
     * @param $data
     * @param $key
     *
     * @return mixed
     */
    public static function signPrivate($data, $key)
    {
        $key = self::trimKey($key);
        $key = "-----BEGIN RSA PRIVATE KEY-----\n{$key}\n-----END RSA PRIVATE KEY-----";
        openssl_sign($data, $sign, $key, \OPENSSL_ALGO_SHA1);

        return $sign;
    }

    /**
     * @param $data
     * @param $fileName
     *
     * @return mixed
     * @throws Exception
     */
    public static function signPrivateFromFile($data, $fileName)
    {
        $key = file_get_contents($fileName);
        $res = openssl_get_privatekey($key);
        if (!$res) {
            throw new Exception('Incorrect public key file format');
        }
        openssl_sign($data, $sign, $res, \OPENSSL_ALGO_SHA1);
        openssl_free_key($res);

        return $sign;
    }

    /**
     * @param $data
     * @param $key
     * @param $sign
     *
     * @return bool
     */
    public static function verifyPublic($data, $key, $sign)
    {
        $key = static::trimKey($key);
        $key = "-----BEGIN PUBLIC KEY-----\n{$key}\n-----END PUBLIC KEY-----";

        return 1 === openssl_verify($data, $sign, $key, \OPENSSL_ALGO_SHA1);
    }

    /**
     * @param $data
     * @param $fileName
     * @param $sign
     *
     * @return bool
     * @throws Exception
     */
    public static function verifyPublicFromFile($data, $fileName, $sign): bool
    {
        $key = file_get_contents($fileName);
        $res = openssl_get_publickey($key);
        if (!$res) {
            throw new Exception('Incorrect public key file format');
        }
        $result = openssl_verify($data, $sign, $res, \OPENSSL_ALGO_SHA1);
        openssl_free_key($res);

        return 1 === $result;
    }

    /**
     * @param $data
     * @param $fileName
     *
     * @return mixed
     * @throws Exception
     */
    public static function encryptPublicFromFile($data, $fileName)
    {
        $res = openssl_get_publickey(file_get_contents($fileName));
        if (!$res) {
            throw new Exception('公钥文件格式错误');
        }
        openssl_public_encrypt($data, $result, $res, \OPENSSL_PKCS1_OAEP_PADDING);
        openssl_free_key($res);

        return $result;
    }

    /**
     * @param $data
     * @param $public
     *
     * @return mixed
     */
    public static function encryptPublic($data, $public)
    {
        openssl_public_encrypt($data, $result, $public, \OPENSSL_PKCS1_OAEP_PADDING);

        return $result;
    }
}