java文档demo,签名实现
1、筛选并排序
将明文业务数据进行JSON化,并按照字符的键值 ASCII 码递增排序(字母升序排序) 此时生成的字符串为待签名字符串。
2、调用签名函数
使用各自语言对应的 SHA256WITHRSA( RSA签名)签名函数利用提供的私钥对签名字符串进行签名,并进行 Base64 编码。把生成的签名 encode 后赋值给 sign 参数
加密
将明文业务数据进行JSON化,使用提供的 AES 密钥加密后, 得到密文,将密文用 Base64 编码后放置到 biz_data 字段中
💡 测试环境和正式环境地址、clientId、RSA私钥、AES密钥请询问我方相关开发或运营人员。
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) throws Exception{
JSONObject data = new JSONObject();
data.put("startTime", "2022-05-01 10:03:00");
data.put("endTime", "2022-05-11 10:03:00");
//RSA私钥
String signPrivateKey="MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCtzlJwMDoum4BayDGsN5SbDANdMbkHatOaJyo8kC7jMDYi1b4gHIms+enjtl+oF2FpI8vjS+uF0dVR8vfgACYqnvosqgWiEiJfnvHBBYq7Bwu7Y51QolzSdR0WhV1IRv8b3mDySrUiQDeVHlUfe66XZw/T+yJG3ZbXRV0OkZMjfwm4/m52hhMBi+DgyGq4fVmi180oWEEgj8pnWx8ut1td7v7hEfIqFPR7QGhVy0gBleaVMpTWfz2O6QCM1Y7Z4LFa8SW5igO5Wg15VpijcS0kll+XiC1+KARZst0lu3xho0vCMwvdJolkpAR5Atp27wvAzlc73ZJHvtA386lqugHrAgMBAAECggEAGUd0/hRFohnD5XBQqTe8SYDJzHg67TVAaZ9gqUZfS3Prq81ixdDgxWPj/Na9uvkLlfs64GhebSxD1pN8MfxTkMdmo7Bm+Veh4D6B8w0XTHSN5EdszhmPXpziCjCDjMumtyr09sie58hnTS0IPHgEwMigqLhSF/SKx+yyyDesKvFFpu9QyrMcKL7W1iMU8W5H9LSB08z1EDY8nJbn6COCRyYdfRLHBcHzwguB0RgA606X/tArjR7HPXSnQd6qzYwJHsR5/2sS+6kIKrDqSUj8IJqGqei6ethX9jeYXHIPvtooym/Dh1mpgRqrmKCN4IeXU30+wR+nUbDMKWMh54mzAQKBgQDlyvYObEjrJjCKWMDS4bPqO+SLaUvSyhZtfpa4b/gskVOll2Y+KQrHMSRWn3XCFtl2YJM40/1+ijnlfJ7p43M3hQGx/au4U2En1fRt1u2ERDblsMvyn3TR1n9m3qOMS16I+18aWPzC4146Li5AG3I6SzHLjZmG28GKD0aRJUMXIQKBgQDBoMQqfKblJfA+cP0XBQBmnszWT3bC2hd5aLn3sMwCXDocE2mh8R1CIWoQurCRUqG1IuR6sw4k9fgjKPpAgxTiSZeORXROcLbw7PE8CR9/y+P0P+qg1IalmytV8N8afxEZBmkACvPuZMyzUlir8kbJNlJAvXSyiwhlk5Xo0vUTiwKBgFr16kxvRLYAWfqJg1p2iVdQ+fjNZ3w7DoGtOFAt0lkh9bB4q7ozWNbcdvvrBxwbG12mgOBf2do7MQvMNsNyi2sQtUkVluHR74VrReQszbwrnGdzgme6Au4FME0yGB8yvmsOxeiSDQvAIM569UffFWpJ1Z4zoPAnEQdrYI2X6GTBAoGALPYZ1wvO7VLb8IPoIRpGN44UXodhOmnOHaEV3dAt7zZfP/m6A6KrepmruWrAaV5YsmkByQQe+rIrBm8TfTty9ADGsoCqOzStJlC+y4QKznAX5LWa0/HFulrHu1MNW2e6HqeAZkQk1GyPo+wxLuw5R6vXebUEjhj+wCd/HesugXUCgYAMVVr0ClRsD9cOxwS6V5e6TJf488KBNyiNyhe0MeecNv2RgaXxeJUmrWyCJCXWbjo/iajGjqk6WpMzNoa6gOUFh2wAgrke9Q810u/kwxHfrUCugYqdOwVE7VIF2bkGjzceTSjdA8uzTa0PRuXKEUROME2jYUAbN6fQk0pJhk/A5w==";
//AES密钥
String aesKey="HtcdQxPS8YD/GiD1";
//String jsonStr = RSA.getSignContent(data);
//根据字段ASCII值排序
String jsonStr = JSON.toJSONString(data, SerializerFeature.MapSortField);
//JSON序列化后 jsonStr : {"endTime":"2022-05-11 10:03:00","startTime":"2022-05-01 10:03:00"}
//RSA加签
String sign = RSA.sign(jsonStr, signPrivateKey);
//rsa签名后 sign:R23pIZMSOq/UsX2s9upnpIiYudZ+aZTN/LoOGKKOCvzwPVxBP2L7ECowA5qHBQcAGM+Y8QPnL0t9UsV8BEeYvDHIoiSovc4WA9ezineII8vsiUF0wxKUC4zzeBrhqh3T5oitPp8azCLCP/VtWfzYYfS0TjEr2oCgeMXxe3pwsgg836kGp3dP9a86a2sfv/eURwUwZc3gdhpJSKZqg1trnszQfiMF6sZK3LduNMIt/oiAp++PjfiAwo9S2atpBJQsIcFjMI3Q1/pHEzhoHZ4vh8deH3PTM2PBBITgAyLsPp/eMA6ziOkHiyxDfl3Cm0a3mSsyEv59xKEHBN85+78prA==
//AES 加密
String encrypt = AES.encrypt(jsonStr, aesKey);
//aes加密后 encrypt:Kne+m17nZ5RllkJ9RNQqzsQs51BRvPfFzc5EYGfJOd8YOVAgRj/vMWAWxs3UHL3mp16+MOEo1YkPexGd6/oNu11rVqQTvGMNztxqKdm4Y+OjN/46ApD0/wbieN5X9AzGav5tiBEqjfXWegtuSrBIbw==
String clientId="aa5c7f29-d103-11ec-9544-00ff8a20f478";
Map<String ,Object> params= new HashMap();
params.put("sign",sign);
params.put("bizData",encrypt);
params.put("clientId",clientId);
//发送post请求
CloseableHttpClient httpclient = HttpClients.createDefault();
URI url=new URI("https://tid.xxx g.cc/api/thirdparty/order/statistics");
HttpPost httppost = new HttpPost(url);
httppost.addHeader("Content-type", "application/json;");
httppost.setHeader("Accept", "application/json");
httppost.setEntity(new StringEntity(JSON.toJSONString(params), Charset.forName("UTF-8")));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
if (entity != null) {
String resStr = EntityUtils.toString(entity);
System.out.println(resStr);
//{"resp_data":{"total":0,"trail":0,"trail_pengding":0,"trail_close":0,"trail_pass":0,"trail_pass_waiting_pay":0,"trail_pass_waiting_send":0,"trail_pass_waiting_delivery":0,"trail_pass_renting":0,"trail_pass_backing":0,"trail_pass_finish":0,"untrail":0},"resp_code":"10000","resp_msg":"成功"}
}
}
}
RSA
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
/**
* @author boan
*/
public class RSA {
private static final String SIGN_ALGORITHMS = "SHA256withRSA";
private static final String CHAR_SET = "UTF-8";
public static String sign(String content, String privateKey) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(CHAR_SET));
byte[] signed = signature.sign();
return Base64.getEncoder().encodeToString(signed);
} catch (Exception ex) {
throw new RuntimeException("RSA 加签异常",ex);
}
}
/**
* RSA验签名检查
* @param content 待签名数据
* @param sign 签名值
* @param ali_public_key 公钥
* @return 布尔值
*/
public static boolean verify(String content, String sign, String ali_public_key){
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] encodedKey = Base64.getDecoder().decode(ali_public_key);
PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
signature.initVerify(pubKey);
signature.update( content.getBytes(CHAR_SET) );
boolean bverify = signature.verify( Base64.getDecoder().decode((sign) ));
return bverify;
}catch (Exception e) {
throw new RuntimeException("验签异常",e);
}
}
}
AesUtils
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
/**
* @author netkiller
*/
public class AesUtils {
public static String encrypt(String input, String key) {
byte[] crypted = null;
try {
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skey);
crypted = cipher.doFinal(input.getBytes());
} catch (Exception e) {
throw new RuntimeException("加密异常",e);
}
java.util.Base64.Encoder encoder = java.util.Base64.getEncoder();
return new String(encoder.encodeToString(crypted));
}
public static String decrypt(String input, String key) {
byte[] output = null;
try {
java.util.Base64.Decoder decoder = java.util.Base64.getDecoder();
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skey);
output = cipher.doFinal(decoder.decode(input));
} catch (Exception e) {
throw new RuntimeException("解密异常",e);
}
return new String(output);
}
}
private static $url = 'https://xxxx.xxxx.cc/api/thirdparty/order/statistics';//测试地址
private static $clientId = 'aa5c7f29-d103-11ec-xxxx-00ff8a20f478';//客户端ID
private static $aesKey = "HtcdQxPS8YD/xxxx";//AES密钥
private static $rsaKey = "MIIEvAIBADANB.../A5w==";
/**
* 99pig
* @param array $options
* @return Client
*/
public static function index($options = []){
//业务数据 注意,开始时间和结束时间差不能超过3个月,统计时间以下单时间为准。
$post_data['startTime'] = date('Y-m-d H:i:s',time()-24*3600*80);//开始时间 '2022-05-01 10:03:00';//
$post_data['endTime'] = date('Y-m-d H:i:s');//结束时间 '2022-05-11 10:03:00';//
ksort($post_data);
$json_data = json_encode($post_data);
$private_key = "-----BEGIN RSA PRIVATE KEY-----\n".chunk_split(self::$rsaKey, 64, "\n")."-----END RSA PRIVATE KEY-----\n";
$data['sign'] = openssl_sign($json_data, $signture, openssl_pkey_get_private($private_key),OPENSSL_ALGO_SHA256) ? base64_encode($signture) : '';
$data['bizData'] = base64_encode(openssl_encrypt($json_data, 'AES-128-ECB', self::$aesKey, OPENSSL_RAW_DATA));//加密后的业务数据
$data['clientId'] = self::$clientId;
return openssl_decrypt(self::curlPost($data,self::$url)['resp_data'], 'AES-128-ECB', self::$aesKey);
}
private static function curlPost($params, $url)
{
$data = json_encode($params);
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_POST,1);
curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,60);
curl_setopt($ch,CURLOPT_HTTPHEADER,['Content-Type: application/json','Content-Length:' . strlen($data)]);
curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$output = curl_exec($ch);
curl_close($ch);
return json_decode($output, true);
}
接口提供方用java语言,java适合
PKCS8
方式,非java语言PKCS1
方式,java改成PKCS8
方式比较麻烦
php的PKCS1方式;java要也要改成此种方式
//$json_data:{"endTime":"2022-05-11 10:03:00","startTime":"2022-05-01 10:03:00"}
//$signature:加密后的结果
//$private_key:rsaKey私钥,带开始和结束标志
//OPENSSL_ALGO_SHA1:#PKCS1方式
//验签成功加密
if (openssl_sign($json_data, $signature, $private_key, OPENSSL_ALGO_SHA1)) {
openssl_private_encrypt($json_data, $signture, $private_key);
}
php的PKCS8方式;java不用改
openssl_sign($json_data, $signture, openssl_pkey_get_private($private_key),OPENSSL_ALGO_SHA256)
? base64_encode($signture)
: ''
image.png加密验签在线:http://www.metools.info/
签名算法选OPENSSL_ALGO_SHA256
私钥密码和密钥(带开始和结束标志)和验签字符串
接口返回数据
^ array:3 [▼
"resp_data" => "wmFSjRRihrh9mYZV5tBGWCURmw6P2VxtOyRKChuD5hC2xFq0aYz3zzOOOvdH8LEDstknNSwu+aRSQN0lQLUM8H1DiMkFcRdmoeY1dKi8OTy1czmaRjXcYtOiS74IXPq6/cUO+2dFOtQ13t4wn26wbsu9+qrPCNYS ▶"
"resp_code" => "10000"
"resp_msg" => "成功"
]
网友评论