Java中加密分為兩種方式一個是對稱加密,另一個是非對稱加密。對稱加密是因為加密和解密的鑰匙相同,而非對稱加密是加密和解密的鑰匙不同。
對稱加密與非對稱加密的區別:
對稱加密稱為密鑰加密,速度快,但加密和解密的鑰匙必須相同,只有通信雙方才能知道密鑰。
非對稱加密稱為公鑰加密,算法更加復雜,速度慢,加密和解密鑰匙不相同,任何人都可以知道公鑰,只有一個人持有私鑰可以解密。
對稱加密解密:
- /*
- * 對稱加密
- */
- private static void secretEncrypt() throws Exception {
- //使用Cipher的實例
- Cipher cipher =Cipher.getInstance("AES");
- //得到加密的鑰匙
- SecretKey key =KeyGenerator.getInstance("AES").generateKey();
- //初始化加密操作,傳遞加密的鑰匙
- cipher.init(Cipher.ENCRYPT_MODE,key);
- //將加密的鑰匙寫入secretKey.key文件中
- FileOutputStream fosKey=new FileOutputStream("secretKey.key");
- ObjectOutputStream oosSecretKey =new ObjectOutputStream(fosKey);
- oosSecretKey.writeObject(key);
- oosSecretKey.close();
- fosKey.close();
- //將加密的內容傳遞進去,返回加密后的二進制數據
- byte [] results =cipher.doFinal("哈哈哈哈哈".getBytes());
- //將加密后的二進制數據寫入到secretContent.dat文件中
- FileOutputStream fosData=new FileOutputStream("secretContent.dat");
- fosData.write(results);
- fosData.close();
- }
- /*
- * 對稱解密
- */
- private static void secretDecrypt() throws Exception{
- Cipher cipher =Cipher.getInstance("AES");
- //獲取文件中的key進行解密
- FileInputStream fisKey=new FileInputStream("secretKey.key");
- ObjectInputStream oisKey =new ObjectInputStream(fisKey);
- Key key =(Key)oisKey.readObject();
- oisKey.close();
- fisKey.close();
- //初始化解密操作,傳遞加密的鑰匙
- cipher.init(Cipher.DECRYPT_MODE,key);
- //獲取文件中的二進制數據
- FileInputStream fisDat=new FileInputStream("secretContent.dat");
- //獲取數據第一種方式
- byte [] src=new byte [fisDat.available()];
- int len =fisDat.read(src);
- int total =0;
- while(total<src.length){
- total +=len;
- len=fisDat.read(src,total,src.length-total);
- }
- //執行解密
- byte [] result=cipher.doFinal(src);
- fisDat.close();
- System.out.println(new String(result));
- // 讀文件中的數據第二種方式
- // ByteArrayOutputStream baos =new ByteArrayOutputStream();
- // copyStream(fisDat, baos);
- // byte [] result=cipher.doFinal(baos.toByteArray());
- // fisDat.close();
- // baos.close();
- }
- // private static void copyStream(InputStream ips,OutputStream ops) throws Exception{
- // byte [] buf =new byte[1024];
- // int len=ips.read(buf);
- // while(len!=-1){
- // ops.write(buf,0,len);
- // len =ips.read(buf);
- // }
- // }
基於口令的對稱加密與解密
系統自動生成的Key不容易記憶,我們可以使用我們容易記憶的口令同過java自帶的一個工具將它轉換成Key,在解密的時候我們就可以通過口令進行解密。
- /*
- * 基於口令的對稱加密
- */
- private static void secretEncrypt() throws Exception {
- //實例化工具
- Cipher cipher2=Cipher.getInstance("PBEWithMD5AndDES");
- //使用該工具將基於密碼的形式生成Key
- SecretKey key2=SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new PBEKeySpec("123".toCharArray()));
- PBEParameterSpec parameterspec=new PBEParameterSpec(new byte[]{1,2,3,4,5,6,7,8},1000);
- //初始化加密操作,同時傳遞加密的算法
- cipher2.init(Cipher.ENCRYPT_MODE,key2,parameterspec);
- //將要加密的數據傳遞進去,返回加密后的數據
- byte [] results =cipher2.doFinal("哈哈哈哈哈".getBytes());
- //將加密后的數據寫入到文件中
- FileOutputStream fosData=new FileOutputStream("zxx.dat");
- fosData.write(results);
- fosData.close();
- }
- /*
- * 基於口令的對稱解密
- */
- private static void secretDecrypt() throws Exception{
- Cipher cipher2=Cipher.getInstance("PBEWithMD5AndDES");
- SecretKey key2=SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new PBEKeySpec("123".toCharArray()));
- PBEParameterSpec parameterspec=new PBEParameterSpec(new byte[]{1,2,3,4,5,6,7,8},1000);
- cipher2.init(Cipher.DECRYPT_MODE,key2,parameterspec);
- FileInputStream fisDat=new FileInputStream("zxx.dat");
- byte [] src=new byte [fisDat.available()];
- int len =fisDat.read(src);
- int total =0;
- while(total<src.length){
- total +=len;
- len=fisDat.read(src,total,src.length-total);
- }
- byte [] result=cipher2.doFinal(src);
- fisDat.close();
- System.out.println(new String(result));
- }
非對稱加密解密:
非對稱加密是公鑰加密,私鑰來解密,這個個人做用的少一點,主要針對於大型的網站大型的企業
- /*
- * 公鑰加密
- */
- private static void PublicEnrypt()throws Exception {
- Cipher cipher =Cipher.getInstance("RSA");
- //實例化Key
- KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
- //獲取一對鑰匙
- KeyPair keyPair=keyPairGenerator.generateKeyPair();
- //獲得公鑰
- Key publicKey=keyPair.getPublic();
- //獲得私鑰
- Key privateKey=keyPair.getPrivate();
- //用公鑰加密
- cipher.init(Cipher.ENCRYPT_MODE, publicKey);
- byte [] result=cipher.doFinal("傳智播客".getBytes("UTF-8"));
- //將Key寫入到文件
- saveKey(privateKey,"zxx_private.key");
- //加密后的數據寫入到文件
- saveData(result,"public_encryt.dat");
- }
- /*
- * 私鑰解密
- */
- private static void privateDecrypt() throws Exception {
- Cipher cipher=Cipher.getInstance("RSA");
- //得到Key
- Key privateKey=readKey("zxx_private.key");
- //用私鑰去解密
- cipher.init(Cipher.DECRYPT_MODE, privateKey);
- //讀數據源
- byte [] src =readData("public_encryt.dat");
- //得到解密后的結果
- byte[] result=cipher.doFinal(src);
- //二進制數據要變成字符串需解碼
- System.out.println(new String(result,"UTF-8"));
- }
- private static void saveData(byte[] result, String fileName) throws Exception {
- // TODO Auto-generated method stub
- FileOutputStream fosData=new FileOutputStream(fileName);
- fosData.write(result);
- fosData.close();
- }
- public static void saveKey(Key key,String fileName)throws Exception{
- FileOutputStream fosKey=new FileOutputStream(fileName);
- ObjectOutputStream oosSecretKey =new ObjectOutputStream(fosKey);
- oosSecretKey.writeObject(key);
- oosSecretKey.close();
- fosKey.close();
- }
- private static Key readKey(String fileName) throws Exception {
- FileInputStream fisKey=new FileInputStream(fileName);
- ObjectInputStream oisKey =new ObjectInputStream(fisKey);
- Key key=(Key)oisKey.readObject();
- oisKey.close();
- fisKey.close();
- return key;
- }
- private static byte[] readData(String filename) throws Exception {
- FileInputStream fisDat=new FileInputStream(filename);
- byte [] src=new byte [fisDat.available()];
- int len =fisDat.read(src);
- int total =0;
- while(total<src.length){
- total +=len;
- len=fisDat.read(src,total,src.length-total);
- }
- fisDat.close();
- return src;
- }
數字簽名:
數字簽名的基礎是公鑰和私鑰的非對稱加密,發送者使用私鑰加密的消息摘要(簽名),接收者使用公鑰解密消息摘要以驗證簽名是否是某個人。
要證明這段數據是你發過來的,並且沒有被別人改過,這就需要用到數字簽名,首先我們對整個文檔進行md5加密得到16個字節,然后把消息摘要和文檔發過去,解密者首先對發過來的文檔進行解密,解密后得到一個摘要(md5),對接收的文檔進行md5加密,得到的md5結果匹配解密后的摘要,如果匹配成功的話證明沒有修改過,我們使用Signature進行簽名
- /*
- * 使用私鑰簽名
- */
- private static void sign()throws Exception {
- //實例化Key
- KeyPairGenerator keyPairGenerator=KeyPairGenerator.getInstance("RSA");
- //獲取一對鑰匙
- KeyPair keyPair=keyPairGenerator.generateKeyPair();
- //獲得公鑰
- PublicKey publicKey=keyPair.getPublic();
- //獲得私鑰
- PrivateKey privateKey=keyPair.getPrivate();
- //數字簽名
- Signature signature =Signature.getInstance("SHA1withRSA");
- signature.initSign(privateKey);//用私鑰簽名
- signature.update("這里簽名".getBytes());//對怎樣的數據進行簽名
- byte [] sign=signature.sign(); //獲取簽名的結果
- //保存公鑰並寫入文件中
- saveKey(publicKey,"zxx_private.key");
- //將簽名后的數據寫入到文件
- saveData(sign,"public_encryt.dat");
- }
- /*
- * 公鑰解密
- */
- private static void verify() throws Exception {
- Signature signture =Signature.getInstance("SHA1withRSA");
- //獲取到公鑰
- PublicKey publicKey=(PublicKey)readKey("zxx_private.key");
- //初始化校驗
- signture.initVerify(publicKey);
- //初始化簽名對象
- signture.update("這里簽名".getBytes());
- //讀數據源
- byte [] sign =readData("public_encryt.dat");
- //返回匹配結果
- boolean isYouSigned=signture.verify(sign);
- //如果返回數據為true則數據沒有發生修改,否則發生修改
- System.out.println(isYouSigned);
- }