package com.anylotto.client;

import sun.misc.BASE64Encoder;
import sun.misc.BASE64Decoder;
import java.io.*;
import java.security.*;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.SecretKey;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class SafeMsgBean
{
    private String srcMsg;
//    private ArrayList props;  //存储原始数据
    private static byte[] bytes = {'r', 'e', '3', 'a', '&', '8', '!', 'n'};    // DES算法要求有一个可信任的随机数源
    private static Log log=LogFactory.getLog(SafeMsgBean.class);

    public SafeMsgBean()
    {
        init();
    }

    //数据DES加密
     public String getDESEncMsg(String ikey) throws Exception {
   //获得加密前原始数据
     String srcMsg = getSrcMsg();
     log.info("[send][des]"+srcMsg);
   //对原始数据进行加密
     byte[] key = getKey(ikey).getBytes(); //生成密钥
     SecretKey deskey = new SecretKeySpec(key, "DES");
     String Algorithm = "DES/CBC/PKCS5Padding"; //定义加密算法,可用 DES,DESede,Blowfish
     Cipher c = Cipher.getInstance(Algorithm);
     IvParameterSpec ivSpec = new IvParameterSpec(bytes);

     c.init(Cipher.ENCRYPT_MODE, deskey, ivSpec);
     byte[] raw = c.doFinal(srcMsg.getBytes());
     
      //对加密后的数据进行BASE64编码
      BASE64Encoder encoder = new BASE64Encoder();
      String encMsg = encoder.encode(raw);
      log.debug("[send][des&base64]"+encMsg);
      return encMsg;
    }

    //数据RSA加密
    public String getRSAEncMsg(String cerpath) throws Exception {

         //从证书中读取公钥
        CertificateFactory  certificatefactory=CertificateFactory.getInstance("X.509");
         FileInputStream fin=new FileInputStream(cerpath);
         X509Certificate  certificate=(X509Certificate)certificatefactory.generateCertificate(fin);
        PublicKey pub = certificate.getPublicKey();

         //获得加密前原始数据
       String srcMsg = getSrcMsg();
       log.info("[send][rsa]"+srcMsg);
       byte[] data=srcMsg.getBytes();

         //用公钥对原始数据进行RSA加密
         Cipher cipher=Cipher.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
         cipher.init(Cipher.ENCRYPT_MODE,pub);
         int blockSize = cipher.getBlockSize();
         int outputSize = cipher.getOutputSize(data.length);
         int leavedSize = data.length % blockSize;
         int blocksSize = leavedSize != 0 ? data.length / blockSize + 1 : data.length / blockSize;
         byte[] raw = new byte[outputSize * blocksSize];
         int j = 0;
         while (data.length - j * blockSize > 0) {
             if (data.length - j * blockSize > blockSize)
                 cipher.doFinal(data, j * blockSize, blockSize, raw, j * outputSize);
             else
                 cipher.doFinal(data, j * blockSize, data.length - j * blockSize, raw, j * outputSize);
             j++;
         }

        //对加密后的数据进行BASE64编码
          BASE64Encoder encoder = new BASE64Encoder();
          String encMsg = encoder.encode(raw);
          log.debug("[send][rsa&base64]"+encMsg);
          return encMsg;

    }



    //数据签名
    public String getSignMsg(String storepath,String genkey,String storePass) throws Exception{

            //KeyStore实例化,从密钥匙库加载KeyStore
            KeyStore ks = KeyStore.getInstance("JKS");
            FileInputStream ksfis = new FileInputStream(storepath);
            BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

            char[] spass = new char[storePass.length()];
            for (int i = 0; i < storePass.length(); i++)
                spass[i] = storePass.charAt(i);

            ks.load(ksbufin, spass);

            //从KeyStore中读取私钥
            PrivateKey priv = (PrivateKey) ks.getKey(genkey, spass);

            //获得签名前原始数据
            String srcMsg = getSrcMsg();

            //进行数字签名
            Signature rsa = Signature.getInstance("SHA1withRSA");
            rsa.initSign(priv);
            rsa.update(srcMsg.getBytes("UTF-16LE"));
            byte[] signText = rsa.sign();

            //对签名后的数据进行BASE64编码
            BASE64Encoder encoder = new BASE64Encoder();
            String signMsg = encoder.encode(signText);
            return signMsg;
    }

    //原始数据串
   public String getSrcMsg() throws Exception {return srcMsg;}

   private String getKey(String Key) {

       if (Key.length() > 8) {
          Key = Key.substring(0, 8);
       }
       while (Key.length() % 8 != 0) {
          Key = Key + "\0";
       }
       return Key;
   }

   //接收DES加密后的数据
   public void setDESEncMsg(String encMsg,String ikey)
       throws Exception
   {
       if(encMsg == null || encMsg.length() <= 0)
       {
           throw new Exception("数据为空！");
       }
       log.debug("[receive][des&base64]"+encMsg);
       //对加密数据进行BASE64解码
       BASE64Decoder decoder=new BASE64Decoder();
       byte[] raw=decoder.decodeBuffer(encMsg);

       //对DES加密数据进行解密
       byte[] key = getKey(ikey).getBytes(); //生成密钥
       SecretKey deskey = new SecretKeySpec(key, "DES"); //定义加密算法,可用 DES,DESede,Blowfish
       String Algorithm = "DES/CBC/PKCS5Padding";
       Cipher c = Cipher.getInstance(Algorithm); //定义加密算法,可用 DES,DESede,Blowfish
       IvParameterSpec ivSpec = new IvParameterSpec(bytes);

       c.init(Cipher.DECRYPT_MODE, deskey, ivSpec);
       byte[] cipherByte = c.doFinal(raw);
       String srcMsg=new String(cipherByte);
       log.info("[receive][des]"+srcMsg);       
       //解密后的数据初始化
       setSrcMsg(srcMsg);
    }

    //接收RSA加密后的数据
    public void setRSAEncMsg(String encMsg,String storepath,String genkey,String storePass)
        throws Exception
    {
        if(encMsg == null || encMsg.length() <= 0)
        {
            throw new Exception("数据为空！");
        }
        log.debug("[receive][rsa&base64]"+encMsg);
      //KeyStore实例化,从密钥匙库加载KeyStore
        KeyStore ks = KeyStore.getInstance("JKS");
        FileInputStream ksfis = null;
        ksfis = new FileInputStream(storepath);
        BufferedInputStream ksbufin = new BufferedInputStream(ksfis);



        char[] spass = new char[storePass.length()];
        for (int i = 0; i < storePass.length(); i++)
            spass[i] = storePass.charAt(i);
        ks.load(ksbufin, spass);

        //从KeyStore中读取私钥
         PrivateKey priv = (PrivateKey) ks.getKey(genkey, spass);

        //对加密数据进行BASE64解码
        BASE64Decoder decoder=new BASE64Decoder();
        byte[] raw=decoder.decodeBuffer(encMsg);

        //对加密的数据进行RSA解密
        Cipher cdes =  Cipher.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());
        cdes.init(Cipher.DECRYPT_MODE, priv);
       int blockSize = cdes.getBlockSize();

       ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
        int j = 0;
        while (raw.length - j * blockSize > 0) {
            bout.write(cdes.doFinal(raw, j * blockSize, blockSize));
            j++;
        }

        String  srcMsg = bout.toString();
        log.info("[receive][rsa]"+srcMsg);       
        //解密后的数据初始化
        setSrcMsg(srcMsg);
    }

    protected void setSrcMsg(String srcMsg) throws Exception {this.srcMsg=srcMsg;}

    public boolean verifySign(String signMsg,String cerpath)throws Exception {

            //从证书中读取公钥
            CertificateFactory  certificatefactory=CertificateFactory.getInstance("X.509");
            FileInputStream fin=new FileInputStream(cerpath);
            X509Certificate  certificate=(X509Certificate)certificatefactory.generateCertificate(fin);
            PublicKey pub = certificate.getPublicKey();

            //初始化数字签名算法实例
            Signature rsa=Signature.getInstance("SHA1withRSA");
            //初始化数字签名算法公钥
            rsa.initVerify(pub);
            //初始化数字签名算法原数据
            String srcMsg = getSrcMsg();
            rsa.update(srcMsg.getBytes("UTF-16LE"));

            //签名数据BASE64解码
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] decMsg=decoder.decodeBuffer(signMsg);

            //签名数据验证
            boolean result=rsa.verify(decMsg);
            return result;
    }

    //初始化实例
    public void init(){
         srcMsg="";
    }

}
