php实现rsa签名和验签
程序员文章站
2022-05-14 15:47:51
...
这两天在弄某支付接口相关的东西,以前没做过这块,在签名和验签的过程中遇到了一些问题,记下来. 首先生成一个1024位的私钥: openssl genrsa -out private.pem 1024 然后根据私钥导出公钥 openssl rsa -in private.pem -pubout -out public.pem php的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 = '0' && c = 'a' && c = 'A' && c
巧合的是写完后通过沟通,对方要我们自行生成一对公私钥后将其中的公/私钥指数和模数发给他们.有的时候可能有的办法比技术实现更方便.附上取公/私钥指数和模数的代码:
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']),#私钥指数
);
}
推荐阅读
-
数据安全管理:RSA加密算法,签名验签流程详解
-
PHP SHA1withRSA加密生成签名及验签
-
OpenSSL和Python实现RSA Key数字签名和验证
-
PHP实现的MD5结合RSA签名算法实例
-
Java实现RSA签名以及验签代码示例
-
openssl 生成摘要、签名和验签接口使用
-
采用数字签名RSA或者DSA实现两个linux机器之间使用ssh不需要用户名和密码
-
JAVA/PHP/C#版RSA验签
-
PHP---微信JS-SDK获取access_token/jsapi_ticket/signature权限签名算法,php/thinkphp实现微信分享自定义文字和图片
-
Delphi微信支付【支持MD5和HMAC-SHA256签名与验签】