按:以下文字涉及RSA對WebService傳遞的數(shù)據(jù)的加密解密,,如果您已經(jīng)熟知RSA或是有其它更好的方法請不要往下看以免浪費時間. WebService采用的協(xié)議是SOAP,,它基于HTTP,而HTTP是明文方式,,也就是說,,采用WebService傳遞的數(shù)據(jù)是明文的。如果是天氣預(yù)報這種公開的只讀信息的WebService無所謂,,如果涉及寫入或是和私密數(shù)據(jù)相關(guān),,那么明文傳遞就有很大的潛在危險性,必須加以遏止,。 一般來說有兩種方法,,一是采用https加密的方式,,另一種是用非對稱加密算法對數(shù)據(jù)加密,,下文提到的RSA就是第二種。 使用RSA對WebService傳遞的信息加密解密的基本思想是:服務(wù)器端提供一個WebService方法byte[] getServerPublicKey(),,客戶端可以以此得到服務(wù)器端的公鑰,,然后使用服務(wù)器端的公鑰對要傳出去的數(shù)據(jù)進行RSA加密,并附帶以自己的公鑰,;服務(wù)器端得到客戶端的請求后,,先用自己的私鑰解密客戶端送來的數(shù)據(jù),得到處理結(jié)果后用客戶端提供的公鑰加密,,然后傳回,;客戶端得到服務(wù)器端的返回數(shù)據(jù)后,用自己的私鑰進行解密,,最終得到了服務(wù)器端的真實數(shù)據(jù),。服務(wù)器端和客戶端各自保存自己的RSA私鑰用于解密,提供給對方RSA公鑰進行加密,,這樣中間傳遞的信息就安全了,。 加密解密示意順序圖: 下面是服務(wù)器端實現(xiàn)類的代碼: package com.heyang; public class ServiceImpl implements IService{ @Override public byte[] getResonse(byte[] params, byte[] clientPublicKey) { try { // 使用自己的私鑰解密客戶端用服務(wù)器端公鑰加密的數(shù)據(jù) String decryptString=SecurityUtil.getCoder().getDecryptString(params); // 要返回的結(jié)果 String response="你好!"+decryptString; // 使用客戶端提供的公鑰對返回的數(shù)據(jù)進行加密 byte[] retval=SecurityUtil.getCoder().getEncryptArray(response, clientPublicKey); return retval; } catch (Exception e) { e.printStackTrace(); return null; } } @Override public byte[] getServerPublicKey() { return SecurityUtil.getCoder().getPublicKey(); } } 客戶端調(diào)用服務(wù)器端的代碼: package com.heyang; import org.codehaus.xfire.XFireFactory; import org.codehaus.xfire.client.XFireProxyFactory; import org.codehaus.xfire.service.Service; import org.codehaus.xfire.service.binding.ObjectServiceFactory; public class Test { public static void main(String[] args) { Service srvcModel = new ObjectServiceFactory().create(IService.class); XFireProxyFactory factory = new XFireProxyFactory(XFireFactory .newInstance().getXFire()); String helloWorldURL = "http://localhost:8080/XfireSample/services/hello"; try { IService srvc = (IService) factory.create(srvcModel, helloWorldURL); // 得到服務(wù)器端的公鑰 byte[] serverPublicKey=srvc.getServerPublicKey(); System.out.print("從服務(wù)器端得到的公鑰為:"); for(byte b:serverPublicKey){ System.out.print(b); } System.out.println(); RSASecurityCoder coder=SecurityUtil.getCoder(); String requestString="世界"; // 使用服務(wù)器端的公鑰對要傳出去的數(shù)據(jù)進行加密 byte[] params=coder.getEncryptArray(requestString, serverPublicKey); // 得到服務(wù)器端的返回結(jié)果 byte[] responseArray=srvc.getResonse(params, coder.getPublicKey()); // 使用自己的私鑰進行解密 String responseString=coder.getDecryptString(responseArray); System.out.println("從服務(wù)器端返回的字符串結(jié)果是:"+responseString); } catch (Exception e) { e.printStackTrace(); } } } 輸出的結(jié)果為: 從服務(wù)器端得到的公鑰為:48-127-9748136942-12272-122-913111503-127-115048-127-1192-127-1270-575108-121578675121-687-32-1165359-2586-50-127114-24-6769-17-128115114982868-11550-121-111-69-494021-48-22-5844-37-8645-115-125-984651-344761-117-7875-34115-101-119164666123-4211-13-103-62-30-587926842-12338-32-91-24-75-1177128103-12-71108-121-122112-712-1089753-2691-7863-6385-41-10210782-8784120344-69-90474108-3661-47089-1261812510046-123-3910723101 從服務(wù)器端返回的字符串結(jié)果是:你好,!世界 服務(wù)器端和客戶端使用的RSA加密解密類代碼: package com.heyang; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; /** * RSA加密解密類 * 說明: * 作者:何楊([email protected]) * 創(chuàng)建時間:2010-12-1 下午06:14:38 * 修改時間:2010-12-1 下午06:14:38 */ public class RSASecurityCoder{ // 非對稱加密密鑰算法 private static final String Algorithm="RSA"; // 密鑰長度,,用來初始化 private static final int Key_Size=1024; // 公鑰 private final byte[] publicKey; // 私鑰 private final byte[] privateKey; /** * 構(gòu)造函數(shù),在其中生成公鑰和私鑰 * @throws Exception */ public RSASecurityCoder() throws Exception{ // 得到密鑰對生成器 KeyPairGenerator kpg=KeyPairGenerator.getInstance(Algorithm); kpg.initialize(Key_Size); // 得到密鑰對 KeyPair kp=kpg.generateKeyPair(); // 得到公鑰 RSAPublicKey keyPublic=(RSAPublicKey)kp.getPublic(); publicKey=keyPublic.getEncoded(); // 得到私鑰 RSAPrivateKey keyPrivate=(RSAPrivateKey)kp.getPrivate(); privateKey=keyPrivate.getEncoded(); } /** * 用公鑰對字符串進行加密 * * 說明: * @param originalString * @param publicKeyArray * @return * @throws Exception * 創(chuàng)建時間:2010-12-1 下午06:29:51 */ public byte[] getEncryptArray(String originalString,byte[] publicKeyArray) throws Exception{ // 得到公鑰 X509EncodedKeySpec keySpec=new X509EncodedKeySpec(publicKeyArray); KeyFactory kf=KeyFactory.getInstance(Algorithm); PublicKey keyPublic=kf.generatePublic(keySpec); // 加密數(shù)據(jù) Cipher cp=Cipher.getInstance(Algorithm); cp.init(Cipher.ENCRYPT_MODE, keyPublic); return cp.doFinal(originalString.getBytes()); } /** * 使用私鑰進行解密 * * 說明: * @param encryptedDataArray * @return * @throws Exception * 創(chuàng)建時間:2010-12-1 下午06:35:28 */ public String getDecryptString(byte[] encryptedDataArray) throws Exception{ // 得到私鑰 PKCS8EncodedKeySpec keySpec=new PKCS8EncodedKeySpec(privateKey); KeyFactory kf=KeyFactory.getInstance(Algorithm); PrivateKey keyPrivate=kf.generatePrivate(keySpec); // 解密數(shù)據(jù) Cipher cp=Cipher.getInstance(Algorithm); cp.init(Cipher.DECRYPT_MODE, keyPrivate); byte[] arr=cp.doFinal(encryptedDataArray); // 得到解密后的字符串 return new String(arr); } public byte[] getPublicKey() { return publicKey; } public static void main(String[] arr) throws Exception{ String str="你好,,世界,! Hello,world!"; System.out.println("準備用公鑰加密的字符串為:"+str); // 用公鑰加密 RSASecurityCoder rsaCoder=new RSASecurityCoder(); byte[] publicKey=rsaCoder.getPublicKey(); byte[] encryptArray=rsaCoder.getEncryptArray(str, publicKey); System.out.print("用公鑰加密后的結(jié)果為:"); for(byte b:encryptArray){ System.out.print(b); } System.out.println(); // 用私鑰解密 String str1=rsaCoder.getDecryptString(encryptArray); System.out.println("用私鑰解密后的字符串為:"+str1); } } 用于初始化RSASecurityCoder實例的SecurityUtil類代碼: package com.heyang; /** * 信息安全實用類 * 說明: * 作者:何楊([email protected]) * 創(chuàng)建時間:2010-12-2 上午10:57:49 * 修改時間:2010-12-2 上午10:57:49 */ public class SecurityUtil{ // 用于加密解密的RSA編碼類 private static RSASecurityCoder coder; /** * 初始化coder的靜態(tài)構(gòu)造子 */ static{ try { coder=new RSASecurityCoder(); } catch (Exception e) { e.printStackTrace(); } } public static RSASecurityCoder getCoder() { return coder; } } 您可以從http://www./shared/cyg98xgz78 獲得上述代碼涉及到的兩個實例工程,。 好了,感謝您看到這里,,希望此文字沒有耽誤您太多寶貴時間,。 |
|
來自: CevenCheng > 《Web安全-黑客》