Java对接C#的RSA加密http接口,C#提供公钥给Java,Java通过公钥去调用C#的http(post)接口

## C#方提供的接口文档:
1.5.2 签名方法
调用API时,需要将所有参数名称以及参数值加入签名,即:系统级参数(除去sign)名称、系统级参数值、应用级参数名称、应用级参数值全部加入签名。
I.签名参数串排序
签名时,根据参数名称,将除签名(sign)外所有请求参数按照字母先后顺序排序:
key + value … key + value 。
注:
1、排序若首字母相同,则对第二个字母进行排序,以此类推。
2、value无需编码。
3、对于非必选参数,如果没有value值,也可不参与签名。(说明:非必选参数没有value值时,将参数名放到字符串中,即参数名要参加签名)
例如:将“foo=1,bar=2,baz=三”排序为“bar=2,baz=三,foo=1”参数名和参数值链接后,得到拼装字符串bar2baz三foo1。
II.签名算法
API会分配一个接口调用的secret,
将分配的得到的secret同时拼接到参数字符串头、尾部进行md5加密,再转化成大写,格式是:md5(secretkey1value1key2value2…secret)。
1.5.3 获取签名代码
调用API时,需要将所有参数名称以及参数值加入签名,即:系统级参数(除去sign)名称、系统级参数值、应用级参数名称、应用级参数值全部加入签名。

## 通过观察文档,发现提供的文档中有调用实例,虽然是C#调用的实例,我的做法是用java对着文档重写C#的调用方法;
要注意的几个问题:
1.确定好两边的编码格式
2.java对参数进行rsa加密之后是一个字节数组,我百度到有很多rsa的util类都是将这个字节数组进行了base64编码,这里要注意确定C#那边是否需要的是base64编码之后的字符串!!!
3.最后进行http传参提交请求时,需要跟接口提供方确定参数应该放在哪里,我这边的接口方参数是放在请求体中的!
4.调用的时候可以用postman进行接口测试。

这个是rsa加密的工具类:

import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;

import java.io.ByteArrayOutputStream;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RSAUtils {
	private static Map<Integer, String> keyMap = new HashMap<Integer, String>(); // 用于封装随机产生的公钥与私钥

	public static void main(String[] args) throws Exception {
		// 生成公钥和私钥
		genKeyPair();
		// 加密字符串
		String message = "df723820";
		System.out.println("随机生成的公钥为:" + keyMap.get(0));
		System.out.println("随机生成的私钥为:" + keyMap.get(1));
		String messageEn = encrypt(message, keyMap.get(0));
		System.out.println(message + "\t加密后的字符串为:" + messageEn);
		String messageDe = decrypt(messageEn, keyMap.get(1));
		System.out.println("还原后的字符串为:" + messageDe);
	}

	/**
	 * 随机生成密钥对
	 * 
	 * @throws NoSuchAlgorithmException
	 */
	public static void genKeyPair() throws NoSuchAlgorithmException {
		// KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
		KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
		// 初始化密钥对生成器,密钥大小为96-1024位
		keyPairGen.initialize(1024, new SecureRandom());
		// 生成一个密钥对,保存在keyPair中
		KeyPair keyPair = keyPairGen.generateKeyPair();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); // 得到私钥
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); // 得到公钥
		String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
		// 得到私钥字符串
		String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
		// 将公钥和私钥保存到Map
		keyMap.put(0, publicKeyString); // 0表示公钥
		keyMap.put(1, privateKeyString); // 1表示私钥
	}

	/**
	 * RSA公钥加密
	 * 
	 * @param str
	 *            加密字符串
	 * @param publicKey
	 *            公钥
	 * @return 密文
	 * @throws Exception
	 *             加密过程中的异常信息
	 */
	public static String encrypt(String str, String publicKey) throws Exception {
		// base64编码的公钥
		byte[] decoded = Base64.decodeBase64(publicKey);
		RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
				.generatePublic(new X509EncodedKeySpec(decoded));
		// RSA加密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.ENCRYPT_MODE, pubKey);
		int length = str.getBytes("UTF-8").length;
		byte[] doFinal = cipher.doFinal(str.getBytes("UTF-8"));
		String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
		StringBuffer sb = new StringBuffer(doFinal.length);
		String sTemp;
		for (int i = 0; i < doFinal.length; i++) {
			sTemp = Integer.toHexString(0xFF & doFinal[i]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		System.out.println("转成16进制字符串===" + sb.toString());
		return sb.toString();
		// return outStr;
	}

	/**
	 * RSA私钥解密
	 * 
	 * @param str
	 *            加密字符串
	 * @param privateKey
	 *            私钥
	 * @return 铭文
	 * @throws Exception
	 *             解密过程中的异常信息
	 */
	public static String decrypt(String str, String privateKey) throws Exception {
		// 64位解码加密后的字符串
		byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
		// base64编码的私钥
		byte[] decoded = Base64.decodeBase64(privateKey);
		RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
				.generatePrivate(new PKCS8EncodedKeySpec(decoded));
		// RSA解密
		Cipher cipher = Cipher.getInstance("RSA");
		cipher.init(Cipher.DECRYPT_MODE, priKey);
		String outStr = new String(cipher.doFinal(inputByte));
		return outStr;
	}

	private static String md5_32;
	private static String md5_16;

	public static String Md5(String sourceStr) {
		String result = "";
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(sourceStr.getBytes());
			byte b[] = md.digest();
			int i;
			StringBuffer buf = new StringBuffer("");
			for (int offset = 0; offset < b.length; offset++) {
				i = b[offset];
				if (i < 0)
					i += 256;
				if (i < 16)
					buf.append("0");
				buf.append(Integer.toHexString(i));
			}
			result = buf.toString();
			md5_32 = result.toUpperCase();
			md5_16 = buf.toString().substring(8, 24).toUpperCase();
			return md5_32;
			// return md5_16;
		} catch (NoSuchAlgorithmException e) {
			System.out.println(e);
		}
		return md5_32;
		// return md5_16;
	}
	
	/** *//**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";
    
    /** *//**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    /** *//**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";
    
    /** *//**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";
    
    /** *//**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    
    /** *//**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

	public static String encryptByPublicKey(String str, String publicKey) throws Exception {
		byte[] data = str.getBytes("UTF-8");
		byte[] keyBytes = Base64Utils.decode(publicKey);
		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
		Key publicK = keyFactory.generatePublic(x509KeySpec);
		// 对数据加密
		Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
		cipher.init(Cipher.ENCRYPT_MODE, publicK);
		int inputLen = data.length;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		int offSet = 0;
		byte[] cache;
		int i = 0;
		// 对数据分段加密
		while (inputLen - offSet > 0) {
			if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
				cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
			} else {
				cache = cipher.doFinal(data, offSet, inputLen - offSet);
			}
			out.write(cache, 0, cache.length);
			i++;
			offSet = i * MAX_ENCRYPT_BLOCK;
		}
		byte[] encryptedData = out.toByteArray();
		StringBuffer sb = new StringBuffer(encryptedData.length);
		String sTemp;
		for (int j = 0; j < encryptedData.length; j++) {
			sTemp = Integer.toHexString(0xFF & encryptedData[j]);
			if (sTemp.length() < 2)
				sb.append(0);
			sb.append(sTemp.toUpperCase());
		}
		System.out.println("转成16进制字符串===" + sb.toString());
		
		out.close();
		return sb.toString();
		//return encryptedData;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值