Maison  >  Article  >  développement back-end  >  Implémentez la signature, le cryptage et la vérification SHA1withRSA à l'aide de PHP

Implémentez la signature, le cryptage et la vérification SHA1withRSA à l'aide de PHP

little bottle
little bottleavant
2019-04-18 11:19:179435parcourir

J'ai vu un code de cryptage de signature PHP partagé par un expert PHP sur Internet. J'aimerais le partager avec vous. Si vous êtes intéressé, venez le découvrir.

Explication du concept :

L'algorithme de hachage sécurisé SHA1 est principalement applicable à l'algorithme de signature numérique défini dans la norme de signature numérique.

RSA est actuellement l'algorithme de chiffrement à clé publique le plus influent. Il peut résister à la grande majorité des attaques cryptographiques connues jusqu'à présent et a été recommandé par l'ISO comme norme de chiffrement de données à clé publique.

SHA1WithRSA : utilisez l'algorithme SHA pour la signature et l'algorithme RSA pour le cryptage.

Exigences commerciales :

Le contenu assemblé par chaque signature est trié et connecté dans l'ordre croissant du dictionnaire des noms de champs

Assemblez le contenu qui doit être signé en premier :

/**
     * 拼接需要签名的内容
     * Author: Tao.
     *
     * @param array $data 需签名的字段内容
     * 
     * @return string
     */     
    public static function getSign($data)
    {
        foreach ($data as $k => $v) {
            $Parameters[$k] = $v;
        }
        //按字典序排序参数
        ksort($Parameters);
        $sign = '';
        foreach ($Parameters as $k => $v) {
            $sign .= $k . "=" . $v . "&";
        }
        $sign = '&' . rtrim($sign, '&');
        return $sign;
    }

La chaîne de signature est la suivante :
&amount=amount value&ccy=ccy value&merchantId=merchantId value¬ifyUrl=notifyUrl value&orderId=orderId value&payeeAcctNo=payeeAcctNo value (texte brut).

Il est à noter qu'en fonction des besoins de l'entreprise, vous pouvez choisir de raccorder ou non l'esperluette avant le contenu de la signature.

Générez ensuite la signature de clé secrète :

/**
     * 秘钥加密
     * Author: Tao.
     *
     * @param string $data 之前生成好的需加密内容
     * @param $key 私钥证书位置(.pfx文件)
     * @param string $pwd 证书密码
     *
     * @return string
     */
    public static function SHA1withRSA($data, $key,$pwd)
    {
        openssl_pkcs12_read(file_get_contents($key), $certs, $pwd); 
        if (!$certs) return;
        $signature = '';
        openssl_sign($data, $signature, $certs['pkey']);
        return bin2hex($signature);  
    }

Étant donné que la société tierce exige une conversion en hexadécimal, vous pouvez choisir bin2hex() ou base64_encode() selon vos besoins .

Ce qu'il convient de noter ici, c'est si le contenu signé doit être sensible à la casse en fonction des besoins de l'entreprise.

Le contenu signé doit être en minuscules et peut être converti en majuscules à l'aide de strtoupper().

Ce qui précède est la méthode de cryptage par clé privée compilée pour tout le monde.

Cependant, cette activité nécessite également que le numéro de carte bancaire soit crypté avec la clé publique RSA
Voici la méthode pour obtenir la clé publique :
Voici Obtenir la clé publique (fichier .cer) du certificat de plateforme de l'autre partie


/**
     * 获取公钥
     * Author: Tao.
     *
     * @param $path //公钥证书位置 (.cer文件)
     *
     * @return mixed
     * @throws \Exception
     */
    public static function loadCert($path)
    {
        $file = file_get_contents($path);
        if (!$file) {
            throw new \Exception('loadx509Cert::file_get_contents ERROR');
        }

        $cert = chunk_split(base64_encode($file), 64, "\n");
        $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "-----END CERTIFICATE-----\n";

        $res = openssl_pkey_get_public($cert);
        $detail = openssl_pkey_get_details($res);
        openssl_free_key($res);

        if (!$detail) {
            throw new \Exception('loadX509Cert::openssl_pkey_get_details ERROR');
        }
        return $detail['key'];
    }

    /**
     * 公钥加密
     * Author: Tao.
     * 
     * @param $pubPath  //公钥证书位置 (.cer文件)
     * @param string $bankCode //银行卡号
     * 
     * @return string
     */
    public static function rsa_encode($bankCode,$pubPath)
    {
        $pubkey = self::loadCert($pubPath);
        $encrypt_data = '';
        openssl_public_encrypt($bankCode, $encrypt_data, $pubkey);
        $encrypt_data = base64_encode($encrypt_data);
        return $encrypt_data;
    }

Vous devez me demander pourquoi la clé privée est bin2hex () et la clé publique est remplacée par base64_encode(). Je ne sais pas pourquoi j'ai demandé et il a dit que c'était 16 bits, mais la demande de signature échouait toujours, je l'ai changée en 64 et cela a réussi. L'autre partie a déclaré que le document était trop ancien et avait été oublié. . Choisissez en fonction de vos besoins

Vérification de la signature du résultat final du rappel

Tout d'abord, retirez le contenu du champ de signature assemblé dans les données de rappel et triez selon la méthode getSign() ci-dessus .
Ensuite, vérifiez :

/**
     * 验证返回的签名是否正确
     *
     * @param string $data 要验证的签名原文
     * @param string $signature 签名内容
      *@param $pubPath  公钥证书位置 (.cer文件)
     *
     * @return bool
     */
    public static function verifyRespondSign($data, $signature,$pubPath)
    {
        $keys = self::loadCert($pubPath);
        $signature = hex2bin($signature);
        $ok = openssl_verify($data, $signature, $keys);
        if ($ok == 1) {
            return true;
        }
        return false;
    }

J'espère que cela vous sera utile. S'il y a quelque chose qui ne va pas, veuillez le signaler, le modifier à temps et apprendre les uns des autres. Tutoriels associés : Tutoriel vidéo PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer