package com.xwf;

import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
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;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class SignTest {

    public static final String KEY_ALGORTHM="RSA";
    
    public static final String SIGNATURE_ALGORITHM="SHA1withRSA";
    
    public static void main(String[] args) {
        try {
            
            Map<String,Object> key = initKey();
            String source = "123456";
            String privateKey = getPrivateKey(key);
            String publicKey = getPublicKey(key);
            
            // 签名
            String sign = sign(source.getBytes(), privateKey);
            System.out.println("sign:" + sign);
            
            // 校验
            boolean result = verify(source.getBytes(), publicKey, sign);
            System.out.println("verify result:" + result);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    
    /**
     * 初始化密钥
     * @return
     * @throws Exception
     */
    public static Map<String,Object> initKey()throws Exception{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
        keyPairGenerator.initialize(1024);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
         
        //公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        //私钥
        RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
         
        Map<String,Object> keyMap = new HashMap<String, Object>(2);
        keyMap.put("PUBLIC_KEY", publicKey);
        keyMap.put("PRIVATE_KEY", privateKey);
         
        return keyMap;
    }
    
    /**
     * 取得公钥,并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
        Key key = (Key) keyMap.get("PUBLIC_KEY");  
        return encryptBASE64(key.getEncoded());     
    }
 
    /**
     * 取得私钥,并转化为String类型
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
        Key key = (Key) keyMap.get("PRIVATE_KEY");  
        return encryptBASE64(key.getEncoded());     
    }
    
    
    /**
     *  用私钥对信息生成数字签名
     * @param data  //加密数据
     * @param privateKeyString    //私钥
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data,String privateKeyString)throws Exception{
        //解密私钥
        byte[] keyBytes = decryptBASE64(privateKeyString);
        //构造PKCS8EncodedKeySpec对象
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取私钥匙对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
        //用私钥对信息生成数字签名
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateKey);
        signature.update(data);
         
        return encryptBASE64(signature.sign());
    }
    
    /**
     * BASE64解密
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptBASE64(String key) throws Exception{
        return (new BASE64Decoder()).decodeBuffer(key);
    }
     
    /**
     * BASE64加密
     * @param key
     * @return
     * @throws Exception
     */
    public static String encryptBASE64(byte[] key)throws Exception{
        return (new BASE64Encoder()).encodeBuffer(key);
    }
    
    /**
     * 校验数字签名
     * @param data  加密数据
     * @param publicKeyString 公钥
     * @param sign  数字签名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data,String publicKeyString,String sign)throws Exception{
        //解密公钥
        byte[] keyBytes = decryptBASE64(publicKeyString);
        //构造X509EncodedKeySpec对象
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
        //指定加密算法
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
        //取公钥匙对象
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
         
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicKey);
        signature.update(data);
        //验证签名是否正常
        return signature.verify(decryptBASE64(sign));
         
    }
}