php java rsa_php实现rsa签名和验签

首先生成一个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 

char hc = hexStr.charAt(2 * i);

char lc = hexStr.charAt(2 * i + 1);

byte hb = hexChar2Byte(hc);

byte lb = hexChar2Byte(lc);

if (hb 

return null;

int n = hb <

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$ 

byte b = arr$[i$];

String tmp = Integer.toHexString(0xff & b);

if (tmp.length() 

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']),#私钥指数

);

}

来自:http://eslizn.com/post/17/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值