Java加密和數字簽名本文主要談壹下密碼學中的加密和數字簽名 以及其在java中如何進行使用 對密碼學有興趣的夥伴 推薦看 Bruce Schneier的著作 Applied Crypotography 在jdk 的發行版本中安全性方面有了很大的改進 也提供了對RSA算法的直接支持 現在我們從實例入手解決問題(本文僅是作為簡單介紹)
壹 密碼學上常用的概念
)消息摘要
這是壹種與消息認證碼結合使用以確保消息完整性的技術 主要使用單向散列函數算法 可用於檢驗消息的完整性 和通過散列密碼直接以文本形式保存等 目前廣泛使用的算法有MD MD SHA jdk 對上面都提供了支持 在java中進行消息摘要很簡單 java security MessageDigest提供了壹個簡易的操作方法
/** *MessageDigestExample java *Copyright */ import java security MessageDigest; /** *單壹的消息摘要算法 不使用密碼 可以用來對明文消息(如 密碼)隱藏保存 */ public class MessageDigestExample{public static void main(String[] args) throws Exception{ if(args length!= ){ System err println( Usage:java MessageDigestExample text ); System exit( ); }
byte[] plainText=args[ ] getBytes( UTF );
//使用getInstance( 算法 )來獲得消息摘要 這裏使用SHA 的 位算法 MessageDigest messageDigest=MessageDigest getInstance( SHA );
System out println( \n +messageDigest getProvider() getInfo()); //開始使用算法 messageDigest update(plainText); System out println( \nDigest: ); //輸出算法運算結果 System out println(new String(messageDigest digest() UTF ));} } 還可以通過消息認證碼來進行加密實現 javax crypto Mac提供了壹個解決方案 有興趣者可以參考相關API文檔 本文只是簡單介紹什麽是摘要算法
這裏補充另壹個運用消息摘要的方式加密的例子: public class TestEncrypt {
public TestEncrypt() { }
/** * @param strSrc :strSrc is a string will be encrypted * @param encName : encName is the algorithm name will be used * encName dafault to MD * @return String */ public String Encrypt(String strSrc String encName) {
MessageDigest md = null; String strDes = null;
byte[] bt = strSrc getBytes(); try { if (encName == null || encName equals( )) { encName = MD ; } md = MessageDigest getInstance(encName); md update(bt); strDes = bytes Hex(md digest()); //to HexString } catch (NoSuchAlgorithmException e) { System out println( Invalid algorithm ); return null; } return strDes; }
public String bytes Hex(byte[] bts) { String des = ; String tmp = null; for (int i = ; i < bts length; i++) { tmp = (Integer toHexString(bts[i] & xFF)); if (tmp length() == ) { des += ; } des += tmp; } return des; }
public static void main(String[]args) { TestEncrypt te = new TestEncrypt(); String strSrc = 可以加密漢字 Oh and english ; System out println( Source String: + strSrc); System out println( Encrypted String: ); System out println( Use Def: + te Encrypt(strSrc null)); System out println( Use MD : + te Encrypt(strSrc MD )); System out println( Use SHA: + te Encrypt(strSrc SHA )); System out println( Use SHA : + te Encrypt(strSrc SHA )); } }
另外 在javawebparts中的 RequestHelpers裏的generateGUID方法也涉及到了MD 的方法 代碼如下: public static String generateGUID(HttpServletRequest request) {
String out = ; try {? // Construct a string that is prised of:? // Remote IP Address + Host IP Address + Date (yyyyMMdd) +? // Time (hhmmssSSa) + Requested Path + Session ID +? // HashCode Of ParameterMap? StringBuffer *** = new StringBuffer( );? *** append(request getRemoteAddr());? InetAddress ia = InetAddress getLocalHost();? *** append(ia getHostAddress());? *** append(new SimpleDateFormat( yyyyMMddhhmmssSSa ) format(new Date()));? String path = request getServletPath();? String pathInfo = request getPathInfo();? if (pathInfo != null) { path += pathInfo;? }? *** append(path);? *** append(request getSession(false));? *** append(request getParameterMap() hashCode());? String str = *** toString();? // Now encode the string using an MD encryption algorithm ? MessageDigest md = MessageDigest getInstance( md );? md update(str getBytes());? byte[] digest = md digest();? StringBuffer hexStr = new StringBuffer( );? for (int i = ; i < digest length; i++) { str = Integer toHexString( xFF & digest[i]); if (str length() < ) {? str = + str; } hexStr append(str);? }? out = hexStr toString(); } catch (NoSuchAlgorithmException nsae) {? log error(nsae); } catch (UnknownHostException uhe) {? log error(uhe); } // Return the encrypted string It should be unique based on the // ponents that prise the plain text string and should always be // characters thanks to the MD algorithm return out;
} // End generateGUID()
)私鑰加密
消息摘要只能檢查消息的完整性 但是單向的 對明文消息並不能加密 要加密明文的消息的話 就要使用其他的算法 要確保機密性 我們需要使用私鑰密碼術來交換私有消息
這種最好理解 使用對稱算法 比如 A用壹個密鑰對壹個文件加密 而B讀取這個文件的話 則需要和A壹樣的密鑰 雙方***享壹個私鑰(而在web環境下 私鑰在傳遞時容易被偵聽)
使用私鑰加密的話 首先需要壹個密鑰 可用javax crypto KeyGenerator產生壹個密鑰(java security Key) 然後傳遞給壹個加密工具(javax crypto Cipher) 該工具再使用相應的算法來進行加密 主要對稱算法有 DES(實際密鑰只用到 位) AES(支持三種密鑰長度 位) 通常首先 位 其他的還有DESede等 jdk 種也提供了對對稱算法的支持 以下例子使用AES算法來加密
/** *PrivateExmaple java *Copyright */ import javax crypto Cipher; import javax crypto KeyGenerator; import java security Key;
/** *私鈅加密 保證消息機密性 */ public class PrivateExample{public static void main(String[] args) throws Exception{ if(args length!= ){ System err println( Usage:java PrivateExample <text> ); System exit( ); } byte[] plainText=args[ ] getBytes( UTF );
//通過KeyGenerator形成壹個key System out println( \nStart generate AES key ); KeyGenerator keyGen=KeyGenerator getInstance( AES ); keyGen init( ); Key key=keyGen generateKey(); System out println( Finish generating DES key );
//獲得壹個私鈅加密類Cipher ECB是加密方式 PKCS Padding是填充方法 Cipher cipher=Cipher getInstance( AES/ECB/PKCS Padding ); System out println( \n +cipher getProvider() getInfo());
//使用私鈅加密 System out println( \nStart encryption: ); cipher init(Cipher ENCRYPT_MODE key); byte[] cipherText=cipher doFinal(plainText); System out println( Finish encryption: ); System out println(new String(cipherText UTF ));
System out println( \nStart decryption: ); cipher init(Cipher DECRYPT_MODE key); byte[] newPlainText=cipher doFinal(cipherText); System out println( Finish decryption: );
System out println(new String(newPlainText UTF ));
} }
)公鑰加密
上面提到 私鑰加密需要壹個***享的密鑰 那麽如何傳遞密鑰呢?web環境下 直接傳遞的話很容易被偵聽到 幸好有了公鑰加密的出現 公鑰加密也叫不對稱加密 不對稱算法使用壹對密鑰對 壹個公鑰 壹個私鑰 使用公鑰加密的數據 只有私鑰能解開(可用於加密) 同時 使用私鑰加密的數據 只有公鑰能解開(簽名) 但是速度很慢(比私鑰加密慢 到 倍) 公鑰的主要算法有RSA 還包括Blowfish Diffie Helman等 jdk 種提供了對RSA的支持 是壹個改進的地方
/** *PublicExample java *Copyright */ import java security Key; import javax crypto Cipher; import java security KeyPairGenerator; import java security KeyPair; /** *壹個簡單的公鈅加密例子 Cipher類使用KeyPairGenerator生成的公鈅和私鈅 */ public class PublicExample{public static void main(String[] args) throws Exception{ if(args length!= ){ System err println( Usage:java PublicExample <text> ); System exit( ); }
byte[] plainText=args[ ] getBytes( UTF ); //構成壹個RSA密鑰 System out println( \nStart generating RSA key ); KeyPairGenerator keyGen=KeyPairGenerator getInstance( RSA ); keyGen initialize( ); KeyPair key=keyGen generateKeyPair(); System out println( Finish generating RSA key );
//獲得壹個RSA的Cipher類 使用公鈅加密 Cipher cipher=Cipher getInstance( RSA/ECB/PKCS Padding ); System out println( \n +cipher getProvider() getInfo());
System out println( \nStart encryption ); cipher init(Cipher ENCRYPT_MODE key getPublic()); byte[] cipherText=cipher doFinal(plainText); System out println( Finish encryption: ); System out println(new String(cipherText UTF ));
lishixinzhi/Article/program/Java/hx/201311/26898