RSA 签名 / 验签工具

本贴最后更新于 1854 天前,其中的信息可能已经渤澥桑田

依赖 jar 包下载

zmxysdkjava20170605134301.jar
zmxysdkjava20170605134301source.jar

代码如下

   import com.antgroup.zmxy.openplatform.api.ZhimaApiException;
   import com.antgroup.zmxy.openplatform.api.internal.util.Base64Util;
   import com.antgroup.zmxy.openplatform.api.internal.util.CoderUtil;
   import com.antgroup.zmxy.openplatform.api.internal.util.EncryptionModeEnum;
   import com.antgroup.zmxy.openplatform.api.internal.util.SignTypeEnum;
   import com.antgroup.zmxy.openplatform.api.internal.util.json.ExceptionErrorListener;
   import com.antgroup.zmxy.openplatform.api.internal.util.json.JSONValidatingReader;
	import java.io.ByteArrayOutputStream;
	import java.security.Key;
	import java.security.KeyFactory;
	import java.security.PrivateKey;
	import java.security.PublicKey;
	import java.security.Signature;
	import java.security.spec.PKCS8EncodedKeySpec;
	import java.security.spec.RSAPrivateKeySpec;
	import java.security.spec.RSAPublicKeySpec;
	import java.security.spec.X509EncodedKeySpec;
	import java.util.Iterator;
	import java.util.Map;
	import javax.crypto.Cipher;

   import org.apache.log4j.Logger;

	public class PKRSACoderUtil extends CoderUtil{
    
  	protected static Logger log = Logger.getLogger(PKRSACoderUtil.class);
  
  	public static final String KEY_ALGORTHM = "RSA";
  	public static final String SPECIFIC_KEY_ALGORITHM = "RSA/ECB/PKCS1Padding";
  	public static final String SIGNATURE_ALGORITHM = "SHA256WITHRSA";
  	public static String encrypt(String paramsString, String charset, String publicKey)
    throws Exception
  	{
    	byte[] encryptedResult = encryptByPublicKey(paramsString.getBytes(charset), publicKey, null);
    	return Base64Util.byteArrayToBase64(encryptedResult);
  	}
 	public static String encrypt(String paramsString, String charset, String publicKey, EncryptionModeEnum encryptionType)
    throws Exception
  	{
    	byte[] encryptedResult = encryptByPublicKey(paramsString.getBytes(charset), publicKey, encryptionType);


    	return Base64Util.byteArrayToBase64(encryptedResult);
  	}


  	public static String sign(String data, String charset, String privateKey)
    throws Exception
  	{
    	byte[] dataInBytes = data.getBytes(charset);
   	 String signParams = sign(dataInBytes, privateKey);
   	 return signParams;
  	}



  	public static String sign(SignTypeEnum signType, String data, String charset, String privateKey)
    throws Exception
  	{
   	 byte[] dataInBytes = data.getBytes(charset);
   	 String signParams = sign(signType, dataInBytes, privateKey);
   	 return signParams;
  	}

  	public static String decrypt(String data, String key, String charset)
    throws Exception
  	{
    	byte[] byte64 = Base64Util.base64ToByteArray(data);
    	byte[] encryptedBytes = decryptByPrivateKey(byte64, key, null);
   	 return new String(encryptedBytes, charset);
  	}


 	 public static String decrypt(String data, String key, String charset, EncryptionModeEnum encryptionType)
    throws Exception
  	{
   	 byte[] byte64 = Base64Util.base64ToByteArray(data);
   	 byte[] encryptedBytes = decryptByPrivateKey(byte64, key, encryptionType);
   	 return new String(encryptedBytes, charset);
 	 }


 	 public static byte[] decryptByPrivateKey(byte[] data, String key, EncryptionModeEnum encryptionType)
    throws Exception
 	 {
   	 byte[] decryptedData = null;


    	byte[] keyBytes = decryptBASE64(key);

    	PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
    	KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    	Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);

   	 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    cipher.init(2, privateKey);

    	int maxDecryptBlockSize;
    	if (encryptionType != null)
     	 maxDecryptBlockSize = getMaxDecryptBlockSizeByEncryptionType(encryptionType);
    	else {
     	 maxDecryptBlockSize = getMaxDecryptBlockSize(keyFactory, privateKey);
    	}

    	ByteArrayOutputStream bout = new ByteArrayOutputStream();
   	 try {
    	  int dataLength = data.length;
    	  for (int i = 0; i < dataLength; i += maxDecryptBlockSize) {
       	 int decryptLength = (dataLength - i < maxDecryptBlockSize) ? dataLength - i : maxDecryptBlockSize;

       	 byte[] doFinal = cipher.doFinal(data, i, decryptLength);
        	bout.write(doFinal);
     	 }
     	 decryptedData = bout.toByteArray();
   	 } finally {
     	 if (bout != null) {
      	  bout.close();
     	 }
   	 }

    	return decryptedData;
  	}


  	public static byte[] encryptByPublicKey(byte[] data, String key, EncryptionModeEnum encryptionType)
    throws Exception
 	 {
    	byte[] encryptedData = null;


    	byte[] keyBytes = decryptBASE64(key);

    	X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
    	KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    	Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);


   	 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
    	cipher.init(1, publicKey);

   	 int maxEncryptBlockSize;
    	if (encryptionType != null)
     	 maxEncryptBlockSize = getMaxEncryptBlockSizeByEncryptionType(encryptionType);
    	else {
     	 maxEncryptBlockSize = getMaxEncryptBlockSize(keyFactory, publicKey);
   	 }

    	ByteArrayOutputStream bout = new ByteArrayOutputStream();
    	try {
     	 int dataLength = data.length;
      	for (int i = 0; i < data.length; i += maxEncryptBlockSize) {
        	int encryptLength = (dataLength - i < maxEncryptBlockSize) ? dataLength - i : maxEncryptBlockSize;

        	byte[] doFinal = cipher.doFinal(data, i, encryptLength);
        	bout.write(doFinal);
     	 }
      	encryptedData = bout.toByteArray();
   	 } finally {
     	 if (bout != null) {
       	 bout.close();
      	}
   	 }
    	return encryptedData;
 	 }

  	public static String sign(byte[] data, String privateKey)
    throws Exception
 	 {
   	 return sign(SignTypeEnum.SHA1WITHRSA, data, privateKey);
 	 }


 	 public static String sign(SignTypeEnum signType, byte[] data, String privateKey)
    throws Exception
  	{
   	 byte[] keyBytes = decryptBASE64(privateKey);

    	PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);

    	KeyFactory keyFactory = KeyFactory.getInstance("RSA");

    	PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);


    	Signature signature = Signature.getInstance(signType.getDesc());
    	signature.initSign(privateKey2);
    	signature.update(data);

   	 return encryptBASE64(signature.sign());
 	 }


  public static boolean verify(byte[] data, String publicKey, String sign)
    throws Exception
  {
    return verify(SignTypeEnum.SHA1WITHRSA, data, publicKey, sign);
  }



  public static boolean verify(SignTypeEnum signType, byte[] data, String publicKey, String sign)
    throws Exception
  {
    byte[] keyBytes = decryptBASE64(publicKey);

    X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);

    KeyFactory keyFactory = KeyFactory.getInstance("RSA");

    PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);

    Signature signature = Signature.getInstance(signType.getDesc());
    signature.initVerify(publicKey2);
    signature.update(data);
    return signature.verify(decryptBASE64(sign));
  }



  public static String decryptResponse(String fullResponse, String privateKey, String charset, EncryptionModeEnum encryptionType)
    throws Exception
  {
    String decryptedRsp = null;
    Map rootJson = parseResponseMap(fullResponse);
    for (Iterator it = rootJson.keySet().iterator(); it.hasNext(); ) {
      String key = (String)it.next();
      if (key.endsWith("_response")) {
        String value = (String)rootJson.get(key);
        decryptedRsp = value;
      }
    }

    if (((Boolean)rootJson.get("encrypted")).booleanValue()) {
      decryptedRsp = decrypt(decryptedRsp, privateKey, charset, encryptionType);
    }
    return decryptedRsp;
  }



  public static void verifySign(String fullResponse, String decryptedBizResponse, String publicKey, String charset)
    throws Exception
  {
    verifySign(SignTypeEnum.SHA1WITHRSA, fullResponse, decryptedBizResponse, publicKey, charset);
  }



  public static void verifySign(SignTypeEnum signType, String fullResponse, String decryptedBizResponse, String publicKey, String charset)
    throws Exception
  {
    Map rootJson = parseResponseMap(fullResponse);
    String sign = (String)rootJson.get("biz_response_sign");

    if ((sign != null) && (sign.length() > 0)) {
      boolean success = verify(signType, decryptedBizResponse.getBytes(charset), publicKey, sign);

      if (!(success))
        throw new ZhimaApiException("验签失败: " + sign.toString());
    }
  }

  public static Map parseResponseMap(String fullResponse)
    throws ZhimaApiException
  {
    JSONValidatingReader reader = new JSONValidatingReader(new ExceptionErrorListener());
    Object rootObj = reader.read(fullResponse);
    if (rootObj instanceof Map) {
      Map rootJson = (Map)rootObj;
      return rootJson;
    }

    throw new ZhimaApiException("返回结果格式有误:" + fullResponse);
  }








  private static int getMaxEncryptBlockSize(KeyFactory keyFactory, Key key)
    throws Exception
  {
    int maxLength = 117;
    try {
      RSAPublicKeySpec publicKeySpec = (RSAPublicKeySpec)keyFactory.getKeySpec(key, RSAPublicKeySpec.class);
      int keyLength = publicKeySpec.getModulus().bitLength();
      maxLength = keyLength / 8 - 11;
    }
    catch (Exception e) {
    }
    return maxLength;
  }






  private static int getMaxEncryptBlockSizeByEncryptionType(EncryptionModeEnum encryptionType)
  {
    if (encryptionType == EncryptionModeEnum.RSA1024)
      return 117;
    if (encryptionType == EncryptionModeEnum.RSA2048) {
      return 245;
    }

    return 117;
  }








  private static int getMaxDecryptBlockSize(KeyFactory keyFactory, Key key)
    throws Exception
  {
    int maxLength = 128;
    try {
      RSAPrivateKeySpec publicKeySpec = (RSAPrivateKeySpec)keyFactory.getKeySpec(key, RSAPrivateKeySpec.class);
      int keyLength = publicKeySpec.getModulus().bitLength();
      maxLength = keyLength / 8;
    }
    catch (Exception e) {
    }
    return maxLength;
  }






  private static int getMaxDecryptBlockSizeByEncryptionType(EncryptionModeEnum encryptionType)
  {
    if (encryptionType == EncryptionModeEnum.RSA1024)
      return 128;
    if (encryptionType == EncryptionModeEnum.RSA2048) {
      return 256;
    }

    return 128;
  }
}

验签代码

/**

 * 验证签名
 * @return
 * @throws Exception 
 */
public static boolean checksign(JSONObject jsonObject,String platpublickey) throws Exception{
	//获取签名
	String sign = jsonObject.getString("sign");
	//json对象转换成map
	Map<String,Object> bizParams = getTextParams(jsonObject);
	String content = unurlgetSignCheckContentV2(bizParams).trim().replace("\\/", "/");
	return PKRSACoderUtil.verify(SignTypeEnum.SHA256WITHRSA, content.getBytes(SysUtil.CHARSET),platpublickey, sign);
}

签名代码

/**
 * 生成签名
 * 
 * 
 * @return
 * 
 */
public static String producesignByJson(JSONObject jsonObject ,String zzrsprivatekey){
	String signstr="";
	try{
			String content = unurlgetSignCheckContentV2(getTextParams(jsonObject)).trim();
			signstr = PKRSACoderUtil.sign(SignTypeEnum.SHA256WITHRSA, content, SysUtil.CHARSET, zzrsprivatekey);
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} catch (Exception e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	return signstr;
}	
  • RSA
    8 引用 • 5 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 399 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 20 关注
  • etcd

    etcd 是一个分布式、高可用的 key-value 数据存储,专门用于在分布式系统中保存关键数据。

    5 引用 • 26 回帖 • 492 关注
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 417 关注
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • flomo

    flomo 是新一代 「卡片笔记」 ,专注在碎片化时代,促进你的记录,帮你积累更多知识资产。

    3 引用 • 80 回帖 • 2 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 451 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 545 关注
  • 安装

    你若安好,便是晴天。

    128 引用 • 1184 回帖
  • 音乐

    你听到信仰的声音了么?

    59 引用 • 509 回帖
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 13 关注
  • WordPress

    WordPress 是一个使用 PHP 语言开发的博客平台,用户可以在支持 PHP 和 MySQL 数据库的服务器上架设自己的博客。也可以把 WordPress 当作一个内容管理系统(CMS)来使用。WordPress 是一个免费的开源项目,在 GNU 通用公共许可证(GPLv2)下授权发布。

    45 引用 • 113 回帖 • 315 关注
  • 微服务

    微服务架构是一种架构模式,它提倡将单一应用划分成一组小的服务。服务之间互相协调,互相配合,为用户提供最终价值。每个服务运行在独立的进程中。服务于服务之间才用轻量级的通信机制互相沟通。每个服务都围绕着具体业务构建,能够被独立的部署。

    96 引用 • 155 回帖
  • ActiveMQ

    ActiveMQ 是 Apache 旗下的一款开源消息总线系统,它完整实现了 JMS 规范,是一个企业级的消息中间件。

    19 引用 • 13 回帖 • 626 关注
  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    261 引用 • 662 回帖
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 636 关注
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    941 引用 • 1458 回帖 • 150 关注
  • FreeMarker

    FreeMarker 是一款好用且功能强大的 Java 模版引擎。

    23 引用 • 20 回帖 • 427 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 10 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3168 引用 • 8207 回帖
  • 自由行
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 423 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 513 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    96 引用 • 330 回帖
  • OnlyOffice
    4 引用 • 24 关注
  • API

    应用程序编程接口(Application Programming Interface)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

    76 引用 • 421 回帖