利用java证书加密和解密 以及产生共同的加密算法

java 证书公钥加密生成xml 使用http post发送到servl et , servlet私钥解密
xml格式
1 :消息格式:
XML 消息格式如下:
<?xml version="1.0" encoding="UTF-8">
<Request>
<Head>
<Signed>Base64(sign((md5(LoginName + | + LoginTimeSpan + | + PassWord)))</Signed>
</Head>
<body>
<LoginName type="string"> Base64(DES(LoginName)</ LoginName>
<LoginTimeSpan type="string"> Base64(DES(LoginTimeSpan))</LoginTimeSpan>
<Password type="string"> Base64(DES(PassWord))(</Password>
</body>
</request>
2 :消息内容采用 DES 算法进行加密处理, DES 的入口参数有三个: Key 、 Data 、 IV 。其中 Key 为 8 个字节共 64 位,是 DES 算法的工作密钥; Data 也为 8 个字节 64 位,是需要进行加密的数据 ,IV 是双方协商好的初始化向量,要求双方一致,最后结果再进行 BASE64 编码处理,及 BASE64(DES( 传输的消息内容 )) 。
3 :发送方在消息体 <Head> 节点中对消息进行签名,防止消息内容在传输途中被篡改 , 由大众版那边提供公钥证书,这边对 Base64(md5(LoginName + | + LoginTimeSpan + | + PassWord)) 进行签名(rsa-sha1)





package com.cmcc.common.util;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.springframework.core.io.ClassPathResource;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.*;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.Date;

/**
 * User: fengxuesong
 * Date: 11-3-29
 * Time: 下午12:03
 */
public class Sign {
    //Des初始化向量 
    public static final byte[] IV = new byte[]{-29, 105, 5, 40, -94, -98, -113, -100};
    public static final String prikey = "00000000";


    public static void main(String args[]) throws Exception {
        String keystorePath = "F:\\idea-projects\\OSP\\src\\main\\webapp\\WEB-INF\\classes\\feinno.keystore";

        String certPath = "F:\\idea-projects\\OSP\\src\\main\\webapp\\WEB-INF\\classes\\feinno.cer";
        
        File keystoreFile=new ClassPathResource("feinno.keystore").getFile();
        File certPathFile=new ClassPathResource("feinno.cer").getFile();
        if(keystoreFile!=null){
            keystorePath=keystoreFile.getPath();
        }
        if(certPathFile!=null){
            certPath=certPathFile.getPath();
        }

        //初始化data
        String loginName = "1";
        String loginTimeSpan = new Date().toString();
        String password = "111111";

        StringBuffer data = new StringBuffer();
        data.append(loginName).append("|").append(loginTimeSpan).append("|").append(password);
        //生成 data  MD5加密
        byte[] headTextWithMD5 = encryptWithMD5(data);

        //------------------私钥加密-----------------
        String storepass = "feinno";//生成证书库时输入的密码
        String storeKeyName = "feinno"; //证书别名

        String headSigned = new BASE64Encoder().encode(sing(headTextWithMD5, storepass, storeKeyName,keystorePath));


        String content = xml2String(encodeDesWithBase64(prikey, loginName), encodeDesWithBase64(prikey, loginTimeSpan), encodeDesWithBase64(prikey, password), headSigned);
        //---------------------发送http请求
        String url = "http://localhost:8080/auth";
        String backinfo = sendPost(content, url);
        System.out.println("validate:" + backinfo);

        //-----------------模拟 收到http请求 收到的xml 生成 bean
//        Request request = xml2Bean(content);
//        String acceptHeadSigned = request.getHead().getSigned();
//        String acceptLoginName = decodeDesWithBase64(prikey, request.getBody().getLoginName());
//        String acceptLoginTimeSpan = decodeDesWithBase64(prikey, request.getBody().getLoginTimeSpan());
//        String acceptPassword = decodeDesWithBase64(prikey, request.getBody().getPassword());
//        StringBuffer acceptData = new StringBuffer();
//        acceptData.append(acceptLoginName).append("|").append(acceptLoginTimeSpan).append("|").append(acceptPassword);
//        //-----------------公钥验证
//        byte[] verifyText = encryptWithMD5(acceptData);// encryptWithMD5(acceptData);
//
//        boolean verifyFlag = verify(verifyText, new BASE64Decoder().decodeBuffer(acceptHeadSigned),certPath);
//        if (verifyFlag)
//            System.out.println("verify success");
//        else
//            System.out.println("verify faile");
    }

    /**
     * @param plainText  需要验证的内容
     * @param headSigned 私钥生成的签名
     * @return
     */
    public static boolean verify(byte[] plainText, byte[] headSigned,String certPath) throws Exception {

        InputStream streamCert = new FileInputStream(certPath);
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Certificate cert = factory.generateCertificate(streamCert);
        Signature rsa = Signature.getInstance("SHA1WithDSA");
        PublicKey publicKey = cert.getPublicKey();
        rsa.initVerify(publicKey);
        rsa.update(plainText);
        if (rsa.verify(headSigned)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param plainText    签名的内容
     * @param storepass    访问证书的密码
     * @param storeKeyName 证书别名
     * @return
     */
    public static byte[] sing(byte[] plainText, String storepass, String storeKeyName , String keystorePath) throws Exception {
        FileInputStream in = new FileInputStream(keystorePath);
        KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(in, storepass.toCharArray());
        //获取私钥
        PrivateKey priKey = (PrivateKey) ks.getKey(storeKeyName, storepass.toCharArray());
        //用私钥签名
        Signature sig = Signature.getInstance("SHA1WithDSA");
        sig.initSign(priKey);

        sig.update(plainText);
        return sig.sign();
    }

    /**
     * 数据MD5加密
     *
     * @param data
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static byte[] encryptWithMD5(StringBuffer data) throws NoSuchAlgorithmException {
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(data.toString().getBytes());
        return md5.digest();
    }


    /**
     * 用 httpClient 发送 post请求
     *
     * @param content 发送内容
     * @param url
     * @return 返回 response
     * @throws IOException
     */
    public static String sendPost(String content, String url) throws IOException {
        String backinfo = "";
        HttpClient httpclient = new HttpClient();
        
        httpclient.getHttpConnectionManager().getParams().setConnectionTimeout(1000);
        PostMethod post = new PostMethod(url);
        post.getParams().setParameter(HttpMethodParams.SO_TIMEOUT,500);

        post.setParameter("sign", content);
        try {
            httpclient.executeMethod(post);
            int code = post.getStatusCode();
            if (code == HttpStatus.SC_OK) {
                backinfo = new String(post.getResponseBodyAsString());
            }
        } finally {
            post.releaseConnection();
        }
        return backinfo;
    }


    /**
     * xml转bean
     *
     * @param xml
     * @return
     */
    public static Request xml2Bean(String xml) throws Exception {

        JAXBContext context = JAXBContext.newInstance(Request.class);
        Unmarshaller um = context.createUnmarshaller();
        InputStream inStream = new ByteArrayInputStream(xml.getBytes());
        Request request = (Request) um.unmarshal(inStream);
        return request;
    }

    /**
     * 生成xml对应的字符转
     *
     * @param loginName     登录名
     * @param loginTimeSpan 时间戳
     * @param password      密码
     * @param headSigned    证书鉴权
     * @return
     * @throws Exception
     */
    public static String xml2String(String loginName, String loginTimeSpan, String password, String headSigned) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Request.class);
        Request request = new Request();
        Head head = new Head();
        head.setSigned(headSigned);
        Body body = new Body();
        body.setLoginName(loginName);
        body.setLoginTimeSpan(loginTimeSpan);
        body.setPassword(password);
        request.setHead(head);
        request.setBody(body);
        Marshaller m = context.createMarshaller();
        OutputStream outStream = new ByteArrayOutputStream();
        m.marshal(request, outStream);
        return outStream.toString();
    }

    /**
     * 数据 Des加密, 并Base64编码, 解决 des 加密数据必须是8个字节的倍数
     *
     * @param priKey 密钥
     * @param data   需要加密的数据
     * @return 已加密数据
     */
    public static String encodeDesWithBase64(String priKey, String data) throws Exception {
        DESKeySpec desKS = new DESKeySpec(priKey.getBytes());
        SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
        SecretKey sk = skf.generateSecret(desKS);
        Cipher cip = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cip.init(Cipher.ENCRYPT_MODE, sk, new IvParameterSpec(IV));
        byte bb[] = cip.doFinal(data.getBytes());
        return new BASE64Encoder().encode(bb);
    }

    /**
     * 数据 Des解密,
     *
     * @param priKey 密钥
     * @param data   以加密数据
     * @return 解密数据
     * @throws Exception
     */
    public static String decodeDesWithBase64(String priKey, String data) throws Exception {
        DESKeySpec desKS = new DESKeySpec(priKey.getBytes());
        SecretKeyFactory skf = SecretKeyFactory.getInstance("DES");
        SecretKey sk = skf.generateSecret(desKS);
        Cipher cip = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cip.init(Cipher.DECRYPT_MODE, sk, new IvParameterSpec(IV));
        byte bb[] = cip.doFinal(new BASE64Decoder().decodeBuffer(data));
        return new String(bb);
    }


    /**
     * 生成xml的bean
     */
    @XmlRootElement
    public static class Request {
        public Request() {
        }

        Head head;
        Body body;

        public Head getHead() {
            return head;
        }

        public void setHead(Head head) {
            this.head = head;
        }

        public Body getBody() {
            return body;
        }

        public void setBody(Body body) {
            this.body = body;
        }
    }

    public static class Head {
        public Head() {
        }

        String signed;

        public String getSigned() {
            return signed;
        }

        public void setSigned(String signed) {
            this.signed = signed;
        }
    }

    public static class Body {
        public Body() {
        }

        String loginName;
        String loginTimeSpan;
        String password;

        public String getLoginName() {
            return loginName;
        }

        public void setLoginName(String loginName) {
            this.loginName = loginName;
        }

        public String getLoginTimeSpan() {
            return loginTimeSpan;
        }

        public void setLoginTimeSpan(String loginTimeSpan) {
            this.loginTimeSpan = loginTimeSpan;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }
    }


}

猜你喜欢

转载自sakajiaofu.iteye.com/blog/1218607