RSA的签名及验签

package com.fshows.proxy.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

/**
 * RSA的签名及验签
 *
 */
public class MyRsaUtil {

    private static final String SIGN_TYPE_RSA = "RSA";

    private static final String SIGN_TYPE_RSA2 = "RSA2";

    private static final String SIGN_ALGORITHMS = "SHA1WithRSA";

    private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";

    private static final int DEFAULT_BUFFER_SIZE = 8192;

    /**
     * RSA/RSA2 生成签名
     * 
     * @param map
     *            包含 sign_type、privateKey、charset
     * @return
     * @throws Exception
     */
    public static String rsaSign(Map map, String privateKey, String charset) throws Exception {
        PrivateKey priKey = null;
        java.security.Signature signature = null;
        String signType = "RSA";
        String content = getSignContent(map);
        map.put("content", content);
        if (SIGN_TYPE_RSA.equals(signType)) {
            priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
            signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
        } else if (SIGN_TYPE_RSA2.equals(signType)) {
            priKey = getPrivateKeyFromPKCS8(SIGN_TYPE_RSA, new ByteArrayInputStream(privateKey.getBytes()));
            signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        } else {
            throw new Exception("不是支持的签名类型 : : signType=" + signType);
        }
        signature.initSign(priKey);

        if (StringUtils.isEmpty(charset)) {
            signature.update(content.getBytes());
        } else {
            signature.update(content.getBytes(charset));
        }

        byte[] signed = signature.sign();

        return new String(Base64.encodeBase64(signed));

    }

    /**
     * 验签方法
     * 
     *            参数的合成字符串格式: key1=value1&key2=value2&key3=value3...
     * @param publicKey
     * @param charset
     * @return
     */
    public static boolean rsaCheck(Map map, String publicKey, String charset) throws Exception {
        java.security.Signature signature = null;
        String sign = (String)map.get("sign");
        String signType = "RSA";
        String content = getSignCheckContentV1(map);
        System.out.println(">>生成签名的参数为:" + content);
        PublicKey pubKey = getPublicKeyFromX509("RSA", new ByteArrayInputStream(publicKey.getBytes()));
        if (SIGN_TYPE_RSA.equals(signType)) {
            signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
        } else if (SIGN_TYPE_RSA2.equals(signType)) {
            signature = java.security.Signature.getInstance(SIGN_SHA256RSA_ALGORITHMS);
        } else {
            throw new Exception("不是支持的签名类型 : signType=" + signType);
        }
        signature.initVerify(pubKey);

        if (StringUtils.isEmpty(charset)) {
            signature.update(content.getBytes());
        } else {
            signature.update(content.getBytes(charset));
        }

        return signature.verify(Base64.decodeBase64(sign.getBytes()));
    }

    public static String getSignCheckContentV1(Map<String, String> params) {
        if (params == null) {
            return null;
        } else {
            params.remove("sign");
            params.remove("sign_type");
            params.remove("charset");
            params.remove("publicKey");
            StringBuffer content = new StringBuffer();
            List<String> keys = new ArrayList(params.keySet());
            Collections.sort(keys);

            for(int i = 0; i < keys.size(); ++i) {
                String key = (String)keys.get(i);
                String value = (String)params.get(key);
                content.append((i == 0 ? "" : "&") + key + "=" + value);
            }

            return content.toString();
        }
    }

    public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, InputStream ins) throws Exception {
        if (ins == null || StringUtils.isEmpty(algorithm)) {
            return null;
        }

        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

        byte[] encodedKey = readText(ins).getBytes();

        encodedKey = Base64.decodeBase64(encodedKey);

        return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
    }

    public static PublicKey getPublicKeyFromX509(String algorithm, InputStream ins) throws Exception {
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);

        StringWriter writer = new StringWriter();
        io(new InputStreamReader(ins), writer, -1);

        byte[] encodedKey = writer.toString().getBytes();

        encodedKey = Base64.decodeBase64(encodedKey);

        return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
    }

    /**
     * 把参数合成成字符串
     * 
     * @param sortedParams
     * @return
     */
    public static String getSignContent(Map<String, String> sortedParams) {
        StringBuffer content = new StringBuffer();
        // app_id,method,charset,sign_type,version,bill_type,timestamp,bill_date
       // String[] sign_param = sortedParams.get("sign_param").split(",");// 生成签名所需的参数
//        List<String> keys = new ArrayList<String>();
//        for (int i = 0; i < sign_param.length; i++) {
//            keys.add(sign_param[i]);
//        }

        List<String> keys = new ArrayList(sortedParams.keySet());
        Collections.sort(keys);

        int index = 0;
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = sortedParams.get(key);
            if (StringUtils.isNotEmpty(key) && StringUtils.isNotEmpty(value)) {
                content.append((index == 0 ? "" : "&") + key + "=" + value);
                index++;
            }    
        }
        return content.toString();
    }



    private static String readText(InputStream ins) throws IOException {
        Reader reader = new InputStreamReader(ins);
        StringWriter writer = new StringWriter();

        io(reader, writer, -1);
        return writer.toString();
    }

    private static void io(Reader in, Writer out, int bufferSize) throws IOException {
        if (bufferSize == -1) {
            bufferSize = DEFAULT_BUFFER_SIZE >> 1;
        }

        char[] buffer = new char[bufferSize];
        int amount;

        while ((amount = in.read(buffer)) >= 0) {
            out.write(buffer, 0, amount);
        }
    }

}

测试类:

package com.fshows.proxy.util;

import com.google.common.collect.Maps;

import java.util.Map;

public class MyRsaTest {

     //static  String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKLPSayxU0VNbM9oe7xfwlAsTN0993nueKh+M8ml2bdwx9exaz7oyDEy0zEpQlMGUf1v8208XJk2JzQ4VKHgJpBjR6sllcmkwEqawIBRdj+QR2xAMdhfTGbHNWVEBddmIgI7MD8uWqLWfQ4JfTpCDfn0NXh/4tbLeYAnxkhWu0ejAgMBAAECgYA87vfT+koAFgozVhd5WR2QhAQAicClker2pMUdI0Vosn0Y7P4GfXjvcOY58Acyq5rkD5I7v+uoK+xgTvTd4NaNej/ptxCkx5wAOw9SBM13LVVUpcuDgb73EmzYFwFJYtql+UEvIwqpLe9Fk/aYkOjoQtpVH5p9VcxD0m020GVggQJBAN4D1Z1U+JOkQO/vbqRINez+/kfxoVh9JOHpZ6w+Ja9smivw/MF33IPd7GGRRTZCKgdnBa8QJrMCfXHImqGu5s0CQQC7u1wOPYUqe/oQL54TDQPY7JAWTtAwB/FkAOasuSlngwysesnP+jFxQpSuI++fvIUoD9ORXqjpcJCAYBudCogvAkAnQzpV1p8XTScGx6sjdnnC7d1+T6cfBRKuuR5SgbMccPJa7wVkGZRv5aFWJ+C7lbvlDz0cFpkhc0FIDBf8m/fJAkEAhyXeo7HOSENwRm7BUd2ww12qbSTX43wUX3X2mqnCEO7bFOBgoQTwyySvfJ4KR+ijw6+BE8odt9B9dq25s1h9qQJBANDnb/ha0LDt1L3DefniaSUcO4hTi4KyX7GqL4hm3GRc0VO8dKY+g/7lmszqb++F9+7WLgph0uYXaVMFHU2a/PE=";
    // static  String publicKey="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiz0mssVNFTWzPaHu8X8JQLEzdPfd57niofjPJpdm3cMfXsWs+6MgxMtMxKUJTBlH9b/NtPFyZNic0OFSh4CaQY0erJZXJpMBKmsCAUXY/kEdsQDHYX0xmxzVlRAXXZiICOzA/Llqi1n0OCX06Qg359DV4f+LWy3mAJ8ZIVrtHowIDAQAB";

    static  String privateKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJXcI2q/AFyrQC9OzkoiYcQ7ThVSAy/YaJypVl3zYVAzKlYKJdViiDgjQ3zuDq6OMgZc3SeZi5b7ozcYJ/5NomDtrcjN61hpzWUhfIphIBxYhnWVRYhSKv70rFpKERWzD1GoG/kKI1AiYXFq+ugHG9vFxxg05+h1t0rLf0cO4SZDAgMBAAECgYAETIRXk5MXFXKJ6ODSD5puXqUmx2t/+91EYTcxCsJH4q/cN/5N2L2/noNZGhshtsKInDFb6XOvqRhNhEvhZ6i4w9YH5Mo8pK9Fw/UBRJHYVusRnMuqPomVqPLTNkEttNq84J1Sw421B4UxFcrzz1Z8nq1qMZ8aQjN7YFIl8W2ZwQJBANDEA9kIyXexflOAWNsVTKlYkstfwOb+EvVkCg3scWtwSJq9EFHNfkLs9uZvFDObsT+1KprvKiXmitNUsEsxVo0CQQC3xDkiWRqH6F4x1EPUDWkuK6KI6BakY+hiWS06dLcRF7f7pCsNPcZEdpMqqzNgzg+tAo71TS9tiS6RA5u5ZmQPAkAdv8D4nYrwFof06DZBSgC5pRiOCKAZip0zAMV6BHaJI+AExOpdbdYPPWtVnQCY9hfFB1EB8RDlg7vGr6vLm0VFAkEAmJ3iRWBy5ERbVk7PNiEdJTcf+Uum4kgHCwa8xTuBfjSQm/CvwIN5UgqYFmuwc8kuw6TITXkY1oODpPO2NLeQiQJBAM59Zu3CFECXCozawtrT6+L88Q/wK/Z4wfoQ/EYuj7nUAf3bwquWKB6lcByosOHxJBL9YtPVBYd38tkrNmEXR/I=";
    static  String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCV3CNqvwBcq0AvTs5KImHEO04VUgMv2GicqVZd82FQMypWCiXVYog4I0N87g6ujjIGXN0nmYuW+6M3GCf+TaJg7a3IzetYac1lIXyKYSAcWIZ1lUWIUir+9KxaShEVsw9RqBv5CiNQImFxavroBxvbxccYNOfodbdKy39HDuEmQwIDAQAB";


    public static void main(String[] args) throws Exception {
        Map map = Maps.newHashMap();
        map.put("app_id", "123");
        map.put("method", "test");


        String result = MyRsaUtil.rsaSign(map, privateKey, "utf-8");
        System.out.println(result);

        System.out.println("----------------");



        Map map2 = Maps.newHashMap();
        map2.put("app_id", "123");
        map2.put("method", "test");
        map2.put("sign",  result);

        boolean flag = MyRsaUtil.rsaCheck(map2, publicKey, "utf-8");
        
        System.out.println(flag);
                
                

    }

}

 

发表评论

邮箱地址不会被公开。