1. 云栖社区>
  2. PHP教程>
  3. 正文

php实现rsa签名和验签

作者:用户 来源:互联网 时间:2017-12-01 14:24:42

接口

php实现rsa签名和验签 - 摘要: 本文讲的是php实现rsa签名和验签, 这两天在弄某支付接口相关的东西,以前没做过这块,在签名和验签的过程中遇到了一些问题,记下来. 首先生成一个1024位的私钥: openssl genrsa -out private.pem 1024 然后根据私钥导出公钥 openssl

这两天在弄某支付接口相关的东西,以前没做过这块,在签名和验签的过程中遇到了一些问题,记下来.

首先生成一个1024位的私钥:

openssl genrsa -out private.pem 1024

然后根据私钥导出公钥

openssl rsa -in private.pem -pubout -out public.pem

php的openssl扩展里已经封装好了签名和验签的方法,分别是openssl_sign和openssl_verify.

function sign($data){    $p = openssl_pkey_get_private(file_get_contents('private.pem'));    openssl_sign($data, $signature, $p);    openssl_free_key($p);    return bin2hex($signature);}function verify($data, $sign){    $p = openssl_pkey_get_public(file_get_contents('public.pem'));    $verify = openssl_verify($data, hex2bin($sign), $p);    openssl_free_key($p);    return $verify > 0;}

实际情况是测试接口并没有提供公私钥,而是提供了公/私钥指数,模数.通过java的RSAPrivateKeySpec和RSAPublicKeySpec来实现签名和验签,遂写了一个jar用命令行来调用:

package org;import java.math.BigInteger;import java.security.KeyFactory;import java.security.PrivateKey;import java.security.Signature;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.RSAPublicKeySpec;/** * @author eslizn * */public class SignVerify {     /**     * @param args     * @throws Exception     */     public static void main(String[] args) throws Exception {         if(args.length == 4 && args[0].equals("sign")){             System.out.println(Sign(args[1], new BigInteger(args[2], 16), new BigInteger(args[3], 16)));             System.exit(0);         }         if(args.length == 5 && args[0].equals("verify")){             System.out.println(Verify(args[1], args[2], new BigInteger(args[3], 16), new BigInteger(args[4], 16)) ? "1" : "0");             System.exit(0);         }     }     /**     * Sign     *     * @param data     * @param mod     * @param exp     * @return     * @throws Exception     */     public static String Sign(String data, BigInteger mod, BigInteger exp) throws Exception{         RSAPrivateKeySpec spec = new RSAPrivateKeySpec(mod, exp);         KeyFactory keyFactory = KeyFactory.getInstance("RSA");         PrivateKey signKey = keyFactory.generatePrivate(spec);         Signature signature = Signature.getInstance("SHA1withRSA");         signature.initSign(signKey);         signature.update(data.getBytes());         return byteArray2HexString(signature.sign());     }     /**     * Verify     *     * @param data     * @param sign     * @param mod     * @param exp     * @return     * @throws Exception     */     public static boolean Verify(String data, String sign, BigInteger mod, BigInteger exp) throws Exception{         RSAPublicKeySpec spec = new RSAPublicKeySpec(mod, exp);         KeyFactory keyFactory = KeyFactory.getInstance("RSA");         java.security.PublicKey verifyKey = keyFactory.generatePublic(spec);         Signature verifier = Signature.getInstance("SHA1withRSA");         verifier.initVerify(verifyKey);         verifier.update(data.getBytes());         return verifier.verify(hexString2ByteArray(sign));     }     public static byte[] hexString2ByteArray(String hexStr){         if (hexStr == null)             return null;         if (hexStr.length() % 2 != 0)             return null;         byte data[] = new byte[hexStr.length() / 2];         for (int i = 0; i < hexStr.length() / 2; i++){             char hc = hexStr.charAt(2 * i);             char lc = hexStr.charAt(2 * i + 1);             byte hb = hexChar2Byte(hc);             byte lb = hexChar2Byte(lc);             if (hb < 0 || lb < 0)                 return null;             int n = hb << 4;             data[i] = (byte)(n + lb);         }        return data;    }    public static byte hexChar2Byte(char c){        if (c >= '0' && c <= '9')            return (byte)(c - 48);        if (c >= 'a' && c <= 'f')            return (byte)((c - 97) + 10);        if (c >= 'A' && c <= 'F')            return (byte)((c - 65) + 10);        else            return -1;    }    public static String byteArray2HexString(byte arr[]){        StringBuilder sbd = new StringBuilder();        byte arr$[] = arr;        int len$ = arr$.length;        for (int i$ = 0; i$ < len$; i$++){        byte b = arr$[i$];        String tmp = Integer.toHexString(0xff & b);        if (tmp.length() < 2)            tmp = (new StringBuilder()).append("0").append(tmp).toString();            sbd.append(tmp);        }        return sbd.toString();    }}

巧合的是写完后通过沟通,对方要我们自行生成一对公私钥后将其中的公/私钥指数和模数发给他们.有的时候可能有的办法比技术实现更方便.附上取公/私钥指数和模数的代码:

function getPrivate($file){    $p = openssl_pkey_get_private(file_get_contents($file));    $res = openssl_pkey_get_details($p);    var_dump($res);    openssl_free_key($p);    return array(        'n' => bin2hex($res['rsa']['n']),#模数        'e' => bin2hex($res['rsa']['e']),#公钥指数        'd' => bin2hex($res['rsa']['d']),#私钥指数    );}

以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索接口 ,以便于您获取更多的相关知识。