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; } } }
利用java证书加密和解密 以及产生共同的加密算法
猜你喜欢
转载自sakajiaofu.iteye.com/blog/1218607
今日推荐
周排行