JDK中帶有部分加密算法的實現類,主要的是java.security和javax.crypto包下的類,還能夠使用Bouncy Castle(豐富JDK中加密算法的不足)jar包是:bcprov-jdk15on-1.57.jar和Commons Codec(簡化JDK中加密的操做)jar包是:commons-codec-1.10.jarhtml
Base64用於網絡中傳輸的數據進行編碼,嚴格意義上屬於編碼的格式,有64個字符的對應的編碼,Base64就是將內容按照該格式進行編碼。能夠對數據編碼和解碼,是可逆的,安全度較低,不過,也能夠做爲最基礎最簡單的加密算法用於加密要求較弱的狀況java
Base64能夠使用JDk中自帶的類實現,還能夠使用Bouncy Castle(簡稱bc)或Commons Codec(簡稱cc)實現算法
加密數據:apache
private static String src="Hello Base64";
導入的類:安全
import java.io.IOException; import org.apache.commons.codec.binary.Base64; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder;
JDk實現主要使用用BASE64Encoder和BASE64Decoder類的方法(注意:在Eclipse中使用JDK的Base64可能會出現找不到的問題,是由於Base64Encoder並不屬於JDK標準庫範疇,可是又包含在了JDK中,須要咱們手動導入\jre\lib目錄下的rt.jar包便可):網絡
public static void jdkBase64(){ try { BASE64Encoder encoder=new BASE64Encoder(); String encode = encoder.encode(src.getBytes()); System.out.println("encode: "+encode); BASE64Decoder decoder=new BASE64Decoder(); String decode=new String(decoder.decodeBuffer(encode)); System.out.println("decode: "+decode); } catch (IOException e) { e.printStackTrace(); } }
bc實現主要是用Base64類的方法:oracle
public static void bouncybastleBase64(){ byte[] encode = org.bouncycastle.util.encoders.Base64.encode(src.getBytes()); System.out.println("encode: "+new String(encode)); byte[] decode = org.bouncycastle.util.encoders.Base64.decode(encode); System.out.println("decode: "+new String(decode)); }
cc實現也是用Base64類,不過與bc的是不同的,不一樣包中的類,只是名字同樣:dom
public static void commonscodecBase64(){ byte[] encode=Base64.encodeBase64(src.getBytes()); System.out.println("encode: "+new String(encode)); //須要轉化爲String byte[] decode = Base64.decodeBase64(encode); System.out.println("decode: "+new String(decode)); }
摘要算法主要分爲MD,SHA和Hmac算法,摘要算法實際上是用於效驗數據完整性的,咱們在下載某些文件時,會有MD5和SHA1值提供咱們效驗下載的文件是否完整,能夠用於根據數據生成其惟一的摘要值,沒法根據摘要值知道原數據,屬於不可逆的ide
加密數據:函數
private static String src="Hello MD";
導入的類:
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD2Digest; import org.bouncycastle.crypto.digests.MD4Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider;
JDK有MD2和MD5的實現,使用的是MessageDigest類,而沒有MD4的實現:
public static void jdkMD5(){ try { MessageDigest md=MessageDigest.getInstance("MD5"); byte[] digest = md.digest(src.getBytes()); System.out.println("JDK MD5: "+Hex.encodeHexString(digest)); //使用的是cc中帶的Hex須要轉換爲十六進制 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public static void jdkMD2(){ try { MessageDigest md=MessageDigest.getInstance("MD2"); byte[] digest = md.digest(src.getBytes()); System.out.println("JDK MD2: "+Hex.encodeHexString(digest)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
而bc這三種都有,使用的是Digest 類:
public static void bcMD4(){ //方式一 // Digest digest=new MD4Digest(); // digest.update(src.getBytes(), 0, src.getBytes().length); // byte[] md4Bytes=new byte[digest.getDigestSize()]; // digest.doFinal(md4Bytes, 0); // System.out.println("BC MD4: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes)); //方式二(經過添加provider的方式,將sun的改成bc的provider) try { Security.addProvider(new BouncyCastleProvider()); //經過添加provider的方式 MessageDigest md=MessageDigest.getInstance("MD4"); byte[] digest = md.digest(src.getBytes()); System.out.println("BC MD4: "+Hex.encodeHexString(digest)); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } public static void bcMD5(){ Digest digest=new MD5Digest(); digest.update(src.getBytes(), 0, src.getBytes().length); byte[] md4Bytes=new byte[digest.getDigestSize()]; digest.doFinal(md4Bytes, 0); System.out.println("BC MD5: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes)); } public static void bcMD2(){ Digest digest=new MD2Digest(); digest.update(src.getBytes(), 0, src.getBytes().length); byte[] md4Bytes=new byte[digest.getDigestSize()]; digest.doFinal(md4Bytes, 0); System.out.println("BC MD2: "+org.bouncycastle.util.encoders.Hex.toHexString(md4Bytes)); }
cc和JDK是同樣的,畢竟是對JDK加密的簡化,直接使用DigestUtils中的方法,很簡單,並且前兩種方法還須要將MD值轉換爲十六進制,cc直接就幫咱們轉了:
public static void ccMD2(){ //有方法直接就能夠轉換十六進制 System.out.println("CC MD2: "+DigestUtils.md2Hex(src.getBytes())); } public static void ccMd5(){ System.out.println("CC MD5: "+DigestUtils.md5Hex(src.getBytes())); }
這裏只是使用SHA-1,其餘類型相似
加密數據:
private static String src="Hello SHA";
要導入的類:
import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.digest.DigestUtils; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.SHA1Digest;import sun.security.provider.SHA;
JDK實現方式(一樣是使用MessageDigest):
public static void jdkSHA1(){ MessageDigest digest; try { digest = MessageDigest.getInstance("SHA"); digest.update(src.getBytes()); System.out.println("JDK SHA1: "+Hex.encodeHexString(digest.digest())); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
bc的實現方式(一樣是Digest 類):
public static void mcSHA1(){ Digest digest=new SHA1Digest(); digest.update(src.getBytes(),0,src.getBytes().length); byte[] sha1Byte1=new byte[digest.getDigestSize()]; digest.doFinal(sha1Byte1, 0); System.out.println("MC SHA1:"+org.bouncycastle.util.encoders.Hex.toHexString(sha1Byte1)); }
cc的實現方式:
public static void ccsha(){ System.out.println("CC sha1:"+DigestUtils.sha1Hex(src)); }
要加密的數據:
private static String src="Hello HMAC";
要導入的類:
import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.crypto.macs.HMac; import org.bouncycastle.crypto.params.KeyParameter;
JDK的實現方式:
public static void jdkHmacMD5(){ try { KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5"); //初始化KeyGenerator SecretKey secretKey=keyGenerator.generateKey(); //產生密鑰 //byte[] key=secretKey.getEncoded(); //得到密鑰(默認生成) byte[] key=Hex.decodeHex(new char[]{'a','a','a','a','a','a','a','a','a','a'}); //手動生成密鑰(十位) SecretKey secretKey2=new SecretKeySpec(key, "HmacMD5"); //還原密鑰 Mac mac=Mac.getInstance(secretKey2.getAlgorithm()); //實例化mac //初始化mac mac.init(secretKey2); byte[] hmacMD5Bytes=mac.doFinal(src.getBytes()); System.out.println("jdk hmacMD5: "+Hex.encodeHexString(hmacMD5Bytes)); } catch (Exception e) { e.printStackTrace(); } }
bc的實現方式:
public static void bcHmacMd5(){ HMac hMac=new HMac(new MD5Digest()); hMac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("aaaaaaaaaa"))); //須要十位密鑰 hMac.update(src.getBytes(),0,src.getBytes().length); byte[] hmacMD5=new byte[hMac.getMacSize()]; hMac.doFinal(hmacMD5, 0); System.out.println("bc hmacMD5: "+org.bouncycastle.util.encoders.Hex.toHexString(hmacMD5)); }
嚴格意義上的加密算法,分爲對稱和非對稱加密算法,所謂對稱是說發送方和接收方的密鑰是同樣的,而非對稱咱們後面再說。由於密鑰同樣因此安全性跟非對稱比較來講就不太安全了
對稱加密算法主要分爲:DES , 3DES(3重DES) , AES(想要替代DES) , PBE(基於口令的對稱算法)
加密數據 :
private static String src="Hello DES";
導入的類:
import java.security.Security; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESKeySpec; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider;
JDK的實現方式:
public static void jdkDES(){ try { //生成key KeyGenerator keyGenerator=KeyGenerator.getInstance("DES"); keyGenerator.init(56); //指定key長度,同時也是密鑰長度(56位) SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料 byte[] key = secretKey.getEncoded(); //生成key //key轉換成密鑰 DESKeySpec desKeySpec=new DESKeySpec(key); SecretKeyFactory factory=SecretKeyFactory.getInstance("DES"); SecretKey key2 = factory.generateSecret(desKeySpec); //轉換後的密鑰 //加密 Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding"); //算法類型/工做方式/填充方式 cipher.init(Cipher.ENCRYPT_MODE, key2); //指定爲加密模式 byte[] result=cipher.doFinal(src.getBytes()); System.out.println("jdkDES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE,key2); //相同密鑰,指定爲解密模式 result = cipher.doFinal(result); //根據加密內容解密 System.out.println("jdkDES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
bc的實現方式,爲了和JDK的實現方式一致(不想記太多類),採用了添加provider的方式 :
public static void bcDES(){ try { //經過改變provider的方式 Security.addProvider(new BouncyCastleProvider()); //生成key,使用bc須要在後面指定"BC" KeyGenerator keyGenerator=KeyGenerator.getInstance("DES","BC"); keyGenerator.getProvider(); keyGenerator.init(56); //指定key長度,同時也是密鑰長度 SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料 byte[] key = secretKey.getEncoded(); //生成key //key轉換成密鑰 DESKeySpec desKeySpec=new DESKeySpec(key); SecretKeyFactory factory=SecretKeyFactory.getInstance("DES"); SecretKey key2 = factory.generateSecret(desKeySpec); //轉換後的密鑰 //加密 Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding"); //算法類型/工做方式/填充方式 cipher.init(Cipher.ENCRYPT_MODE, key2); byte[] result=cipher.doFinal(src.getBytes()); System.out.println("bcDES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE,key2); //相同密鑰 result = cipher.doFinal(result); //根據加密內容解密 System.out.println("bcDES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
就是記得添加bc的provider,和KeyGenerator.getInstance的參數("DES","BC")
要加密的數據:
private static String src="Hello 3DES";
導入的類:
import java.security.SecureRandom; import java.security.Security; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.DESedeKeySpec; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider;
JDK的實現方法:
public static void jdkDES(){ try { //生成key KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede"); //keyGenerator.init(112); //3DES須要112 or 168位 keyGenerator.init(new SecureRandom()); //或者使用這種方式默認長度,無需指定長度 SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料 byte[] key = secretKey.getEncoded(); //生成key //key轉換成密鑰 DESedeKeySpec desKeySpec=new DESedeKeySpec(key); SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede"); SecretKey key2 = factory.generateSecret(desKeySpec); //轉換後的密鑰 //加密 Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding"); //算法類型/工做方式/填充方式 cipher.init(Cipher.ENCRYPT_MODE, key2); //指定爲加密模式 byte[] result=cipher.doFinal(src.getBytes()); System.out.println("jdk3DES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE,key2); //相同密鑰,指定爲解密模式 result = cipher.doFinal(result); //根據加密內容解密 System.out.println("jdk3DES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
bc的實現方式:
public static void bcDES(){ try { //經過改變provider的方式,其餘操做同樣 Security.addProvider(new BouncyCastleProvider()); //生成key KeyGenerator keyGenerator=KeyGenerator.getInstance("DESede"); keyGenerator.init(new SecureRandom()); SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料 byte[] key = secretKey.getEncoded(); //生成key //key轉換成密鑰 DESedeKeySpec desKeySpec=new DESedeKeySpec(key); SecretKeyFactory factory=SecretKeyFactory.getInstance("DESede"); SecretKey key2 = factory.generateSecret(desKeySpec); //轉換後的密鑰 //加密 Cipher cipher=Cipher.getInstance("DESede/ECB/PKCS5Padding"); //算法類型/工做方式/填充方式 cipher.init(Cipher.ENCRYPT_MODE, key2); //指定爲加密模式 byte[] result=cipher.doFinal(src.getBytes()); System.out.println("jdk3DES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE,key2); //相同密鑰,指定爲解密模式 result = cipher.doFinal(result); //根據加密內容解密 System.out.println("jdk3DES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
基本實現和DES相似,只不過在實現該算法的時候,設置密鑰長度大於128會出現錯誤:Illegal key size or default parameters,這是由於美國的出口限制,Sun經過權限文件(local_policy.jar、US_export_policy.jar)作了相應限制,Oracle在其官方網站上提供了無政策限制權限文件(Unlimited Strength Jurisdiction Policy Files),咱們只須要將其部署在JRE環境中,就能夠解決限制問題
JDK8的無政策限制權限文件(http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html)
將下載的local_policy.jar和US_export_policy.jar替換JDK的JRE環境中,或者是JRE環境中上述兩個jar文件便可
非對稱的ELGamal加密算法算法也有該問題,解決方法相同
加密的數據:
private static String src="Hello AES";
導入的類:
import java.security.Key; import java.security.SecureRandom; import java.security.Security; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.jce.provider.BouncyCastleProvider;
JDK的實現:
public static void jdkAES(){ try { //生成key KeyGenerator keyGenerator=KeyGenerator.getInstance("AES"); keyGenerator.init(new SecureRandom()); SecretKey secretKey = keyGenerator.generateKey(); byte[] key1 = secretKey.getEncoded(); //key轉換爲密鑰 Key key2 = new SecretKeySpec(key1, "AES"); //加密 Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding"); cipher.init(Cipher.ENCRYPT_MODE, key2); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("jdkAES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE, key2); result = cipher.doFinal(result); System.out.println("jdkAES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
bc的實現(一樣使用了添加provider的作法):
public static void bcAES(){ try { Security.addProvider(new BouncyCastleProvider()); //生成key KeyGenerator keyGenerator=KeyGenerator.getInstance("AES", "BC"); keyGenerator.getProvider(); keyGenerator.init(128); //顯示指定密鑰長度 SecretKey secretKey = keyGenerator.generateKey(); byte[] key1 = secretKey.getEncoded(); //key轉換爲密鑰 Key key2 = new SecretKeySpec(key1, "AES"); //加密 Cipher cipher=Cipher.getInstance("AES/ECB/PKCS5padding"); cipher.init(Cipher.ENCRYPT_MODE, key2); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("jdkAES加密: "+Hex.encodeHexString(result)); //轉換爲十六進制 //解密 cipher.init(Cipher.DECRYPT_MODE, key2); result = cipher.doFinal(result); System.out.println("jdkAES解密: "+new String(result)); //轉換字符串 } catch (Exception e) { e.printStackTrace(); } }
基於口令的對稱加密算法(它實際上是對以前的算法的包裝,好比說MD5和DES,我這裏就是的是對MD5和DES包裝的PBE算法,還有其餘類型的PBE),口令就是咱們俗話說的密碼,PBE中有一個salt(鹽)的概念,鹽就是干擾碼
加密的數據:
private static String src="Hello PBE";
導入的類:
import java.security.Key; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.apache.commons.codec.binary.Base64;
JDk的實現:
public static void jdkPBE(){ try { //初始化鹽 SecureRandom random=new SecureRandom(); byte[] salt = random.generateSeed(8); //指定爲8位的鹽 (鹽就是干擾碼,經過添加干擾碼增長安全) //口令和密鑰 String password="lynu"; //口令 PBEKeySpec pbeKeySpec=new PBEKeySpec(password.toCharArray()); SecretKeyFactory factory=SecretKeyFactory.getInstance("PBEWITHMD5andDES"); Key key=factory.generateSecret(pbeKeySpec); //密鑰 //加密 PBEParameterSpec pbeParameterSpec=new PBEParameterSpec(salt, 100); //參數規範,第一個參數是鹽,第二個是迭代次數(通過散列函數屢次迭代) Cipher cipher=Cipher.getInstance("PBEWITHMD5andDES"); cipher.init(Cipher.ENCRYPT_MODE, key,pbeParameterSpec); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("jdk PBE加密: "+Base64.encodeBase64String(result)); //解密 cipher.init(Cipher.DECRYPT_MODE, key,pbeParameterSpec); result = cipher.doFinal(result); System.out.println("jdk PBE解密: "+new String(result)); } catch (Exception e) { e.printStackTrace(); } }
非對稱算法就是發送方和接收方的密鑰是不同的,非對稱相對於對稱來講,有公鑰和私鑰的概念,基本上公鑰是公開的,好比會在網絡上傳輸,而私鑰安全性要求就要高不少了,由於私鑰是要保密的
基本的非對稱算法有DH,RSA,ELGamal算法
DH:
基於交換交換的非對稱算法,接收方須要獲得接收方的key構建本地密鑰,而接收方也須要獲得發送方的key構建本身本地的密鑰。只有JDK的實現
須要加密的數據:
private static String src="Hello DH";
須要導入的類:
import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.X509EncodedKeySpec; import java.util.Objects; import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import javax.crypto.interfaces.DHPublicKey; import javax.crypto.spec.DHParameterSpec;
JDK的實現:
public static void jdkDH(){ try { //初始化發送方密鑰 KeyPairGenerator senderKeyPairGenerator=KeyPairGenerator.getInstance("DH"); senderKeyPairGenerator.initialize(512); //密鑰長度 KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair(); byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded(); //發送方key,需傳遞給接收方(網絡,文件) //初始化接收方密鑰 KeyFactory factory=KeyFactory.getInstance("DH"); X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(senderPublicKeyEnc); //根據從發送方獲得的key解析 PublicKey receiverPublicKey=factory.generatePublic(x509EncodedKeySpec); DHParameterSpec dhParameterSpec=((DHPublicKey)receiverPublicKey).getParams(); KeyPairGenerator receiverKeyPairGenerator=KeyPairGenerator.getInstance("DH"); receiverKeyPairGenerator.initialize(dhParameterSpec); KeyPair receiverKeyPair = receiverKeyPairGenerator.generateKeyPair(); PrivateKey receiverPrivateKey = receiverKeyPair.getPrivate(); byte[] receiverPublicKeyEnc = receiverKeyPair.getPublic().getEncoded(); //密鑰構建 KeyAgreement receiverKeyAgreement=KeyAgreement.getInstance("DH"); receiverKeyAgreement.init(receiverPrivateKey); receiverKeyAgreement.doPhase(receiverPublicKey, true); SecretKey receiverDESKey=receiverKeyAgreement.generateSecret("DES"); //發送發密鑰(公鑰) KeyFactory senderKeyFactory=KeyFactory.getInstance("DH"); x509EncodedKeySpec=new X509EncodedKeySpec(receiverPublicKeyEnc); PublicKey senderPublicKey=senderKeyFactory.generatePublic(x509EncodedKeySpec); KeyAgreement senderKeyAgreement=KeyAgreement.getInstance("DH"); senderKeyAgreement.init(senderKeyPair.getPrivate()); senderKeyAgreement.doPhase(senderPublicKey, true); SecretKey senderDESKey=senderKeyAgreement.generateSecret("DES"); //接收方密鑰(私鑰) if(Objects.equals(receiverDESKey, senderDESKey)){ System.out.println("雙方密鑰相同"); } //加密 Cipher cipher=Cipher.getInstance("DES"); cipher.init(Cipher.ENCRYPT_MODE, senderDESKey); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("jdk DH加密: "+org.apache.commons.codec.binary.Base64.encodeBase64String(result)); //解密 cipher.init(Cipher.DECRYPT_MODE, receiverDESKey); result=cipher.doFinal(result); System.out.println("jdk DH解密: "+new String(result)); } catch (Exception e) { e.printStackTrace(); } }
RSA相較於DH算法的實現簡單,適用範圍較廣,公鑰和私鑰的建立較簡單,並且支持公鑰加密,私鑰解密或者是私鑰加密,公鑰解密兩種方式
要加密的數據:
private static String src="Hello RSA";
要導入的類:
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; import org.apache.commons.codec.binary.Base64;
JDK的實現,公鑰加密,私鑰解密和私鑰加密,公鑰解密兩種方式:
public static void jdkRSA(){ try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(512); KeyPair keyPair = keyPairGenerator.generateKeyPair(); RSAPublicKey rsaPublicKey=(RSAPublicKey) keyPair.getPublic(); //公鑰 RSAPrivateKey rsaPrivateKey=(RSAPrivateKey) keyPair.getPrivate(); //私鑰 System.out.println("public key:"+Base64.encodeBase64String(rsaPublicKey.getEncoded())); System.out.println("private key:"+Base64.encodeBase64String(rsaPrivateKey.getEncoded())); //私鑰加密,公鑰解密--加密 PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); KeyFactory keyFactory=KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher=Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, privateKey); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("RSA私鑰加密,公鑰解密--加密:"+Base64.encodeBase64String(result)); //私鑰加密,公鑰解密--解密 X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded()); keyFactory=KeyFactory.getInstance("RSA"); PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec); cipher=Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE,publicKey); result = cipher.doFinal(result); System.out.println("RSA私鑰加密,公鑰解密--解密:"+new String(result)); //公鑰加密,私鑰解密--加密 x509EncodedKeySpec=new X509EncodedKeySpec(rsaPublicKey.getEncoded()); keyFactory=KeyFactory.getInstance("RSA"); publicKey=keyFactory.generatePublic(x509EncodedKeySpec); cipher=Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE,publicKey); result = cipher.doFinal(src.getBytes()); System.out.println("RSA公鑰加密,私鑰解密--加密:"+Base64.encodeBase64String(result)); //公鑰加密,私鑰解密--解密 pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(rsaPrivateKey.getEncoded()); keyFactory=KeyFactory.getInstance("RSA"); privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec); cipher=Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE,privateKey); result=cipher.doFinal(result); System.out.println("RSA公鑰加密,私鑰解密--解密:"+new String(result)); } catch (Exception e) { e.printStackTrace(); } }
ELGamal算法的和AES同樣存在密鑰長度的限制,解決方法和AES一致。不過ELGamal只支持公鑰加密,私鑰解密這種方式。只有bc的實現方式
要加密的數據:
private static String src="Hello ELGamal";
導入的類:
import java.security.AlgorithmParameterGenerator; import java.security.AlgorithmParameters; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.Security; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import javax.crypto.Cipher; import javax.crypto.spec.DHParameterSpec; import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider;
bc的實現方式:
public static void bcELGamal(){ try { //加載provider Security.addProvider(new BouncyCastleProvider()); //初始化密鑰 AlgorithmParameterGenerator algorithmParameterGenerator=AlgorithmParameterGenerator.getInstance("ELGamal"); algorithmParameterGenerator.init(256); AlgorithmParameters algorithmParameters=algorithmParameterGenerator.generateParameters(); DHParameterSpec dhParameterSpec=(DHParameterSpec)algorithmParameters.getParameterSpec(DHParameterSpec.class); KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("ELGamal"); keyPairGenerator.initialize(dhParameterSpec, new SecureRandom()); KeyPair keyPair=keyPairGenerator.generateKeyPair(); PublicKey elGamalPublicKey=keyPair.getPublic(); //公鑰 PrivateKey elGamalPrivateKey=keyPair.getPrivate(); //私鑰 System.out.println("public key:"+Base64.encodeBase64String(elGamalPublicKey.getEncoded())); System.out.println("private key:"+Base64.encodeBase64String(elGamalPrivateKey.getEncoded())); //公鑰加密,私鑰解密--加密 X509EncodedKeySpec x509EncodedKeySpec=new X509EncodedKeySpec(elGamalPublicKey.getEncoded()); KeyFactory keyFactory=KeyFactory.getInstance("ELGamal"); PublicKey publicKey=keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher=Cipher.getInstance("ELGamal"); cipher.init(Cipher.ENCRYPT_MODE,publicKey); byte[] result = cipher.doFinal(src.getBytes()); System.out.println("ELGamal加密:"+Base64.encodeBase64String(result)); //公鑰加密,私鑰解密--解密 PKCS8EncodedKeySpec pkcs8EncodedKeySpec=new PKCS8EncodedKeySpec(elGamalPrivateKey.getEncoded()); keyFactory=KeyFactory.getInstance("ELGamal"); PrivateKey privateKey =keyFactory.generatePrivate(pkcs8EncodedKeySpec); cipher=Cipher.getInstance("ELGamal"); cipher.init(Cipher.DECRYPT_MODE,privateKey); result=cipher.doFinal(result); System.out.println("ElGamal解密:"+new String(result)); } catch (Exception e) { e.printStackTrace(); } }