1. 程式人生 > >Java對稱與非對稱加密解密,AES與RSA

Java對稱與非對稱加密解密,AES與RSA

加密技術可以分為對稱與非對稱兩種.

對稱加密,解密,即加密與解密用的是同一把祕鑰,常用的對稱加密技術有DES,AES等

而非對稱技術,加密與解密用的是不同的祕鑰,常用的非對稱加密技術有RSA等

為什麼要有非對稱加密,解密技術呢

假設這樣一種場景A要傳送一段訊息給B,但是又不想以明文傳送,所以就需要對訊息進行加密.如果採用對稱加密技術,那麼加密與解密用的是同一把祕鑰.除非B事先就知道A的祕鑰,並且儲存好.這樣才可以解密A發來的訊息.

由於對稱技術只有一把祕鑰,所以祕鑰的管理是一個很麻煩的問題.而非對稱技術的誕生就解決了這個問題.非對稱加密與解密使用的是不同的祕鑰,並且祕鑰對是一一對應的,即用A的私鑰加密的密文只有用A的公鑰才能解密.

這樣的話,每個人都有兩把祕鑰,私鑰和公鑰,私鑰是隻有自己才知道的,不能告訴別人,而公鑰是公開的,大家都可以知道.這樣,當A想要傳送訊息給B的時候,只需要用B的公鑰對訊息進行加密就可以了,由於B的私鑰只有B才擁有,所以A用B的公鑰加密的訊息只有B才能解開.而B想更換自己的祕要時也很方便,只須把公鑰告訴大家就可以了.

那麼,既然非對稱加密如此之好,對稱加密就沒有存在的必要了啊,其實不然,由於非對稱加密演算法的開銷很大,所以如果直接以非對稱技術來加密傳送的訊息效率會很差.那麼怎麼辦呢?解決的辦法也很簡單,就是把對稱加密技術與非對稱加密技術結合起來使用.

還是這個例子:A要傳送一個訊息給B.

一,A先生成一個對稱祕鑰,這個祕鑰可以是隨機生成的,

二,A用B的公鑰加密第一步生成的這個對稱祕鑰

三,A把加密過的對稱祕鑰發給B

四,A用第一步生成的這個對稱祕鑰加密實際要發的訊息

五,A把用對稱祕鑰加密的訊息發給B

對於B

他先收到A發來的對稱祕鑰,這個祕鑰是用B的公鑰加密過的,所以B需要用自己的私鑰來解密這個祕鑰

然後B又收到A發來的密文,這時候用剛才解密出來的祕鑰來解密密文

這樣子的整個過程既保證了安全,又保證了效率.

接下來是Java實現:

我這個Java實現使用的是AES的對稱加密和RSA的非對稱加密(DES的對稱加密實現方法和AES的是一樣的,但是由於DES演算法本身有缺陷,容易被破解,所以現在多用其升級版AES對稱加密)

AES對稱加密,解密

Java程式碼  收藏程式碼
  1. import java.io.IOException;  
  2. import java.io.InputStream;  
  3. import java.io.OutputStream;  
  4. import java.security.InvalidKeyException;  
  5. import java.security.Key;  
  6. import java.security.NoSuchAlgorithmException;  
  7. import java.security.SecureRandom;  
  8. import javax.crypto.BadPaddingException;  
  9. import javax.crypto.Cipher;  
  10. import javax.crypto.IllegalBlockSizeException;  
  11. import javax.crypto.KeyGenerator;  
  12. import javax.crypto.NoSuchPaddingException;  
  13. import javax.crypto.ShortBufferException;  
  14. publicclass AES {  
  15.     private Key key;  
  16.     /** 
  17.      * 生成AES對稱祕鑰 
  18.      * @throws NoSuchAlgorithmException 
  19.      */
  20.     publicvoid generateKey() throws NoSuchAlgorithmException {  
  21.         KeyGenerator keygen = KeyGenerator.getInstance("AES");  
  22.         SecureRandom random = new SecureRandom();  
  23.         keygen.init(random);  
  24.         this.key = keygen.generateKey();  
  25.     }  
  26.     /** 
  27.      * 加密 
  28.      * @param in 
  29.      * @param out 
  30.      * @throws InvalidKeyException 
  31.      * @throws ShortBufferException 
  32.      * @throws IllegalBlockSizeException 
  33.      * @throws BadPaddingException 
  34.      * @throws NoSuchAlgorithmException 
  35.      * @throws NoSuchPaddingException 
  36.      * @throws IOException 
  37.      */
  38.     publicvoid encrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {  
  39.         this.crypt(in, out, Cipher.ENCRYPT_MODE);  
  40.     }  
  41.     /** 
  42.      * 解密 
  43.      * @param in 
  44.      * @param out 
  45.      * @throws InvalidKeyException 
  46.      * @throws ShortBufferException 
  47.      * @throws IllegalBlockSizeException 
  48.      * @throws BadPaddingException 
  49.      * @throws NoSuchAlgorithmException 
  50.      * @throws NoSuchPaddingException 
  51.      * @throws IOException 
  52.      */
  53.     publicvoid decrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {  
  54.         this.crypt(in, out, Cipher.DECRYPT_MODE);  
  55.     }  
  56.     /** 
  57.      * 實際的加密解密過程 
  58.      * @param in 
  59.      * @param out 
  60.      * @param mode 
  61.      * @throws IOException 
  62.      * @throws ShortBufferException 
  63.      * @throws IllegalBlockSizeException 
  64.      * @throws BadPaddingException 
  65.      * @throws NoSuchAlgorithmException 
  66.      * @throws NoSuchPaddingException 
  67.      * @throws InvalidKeyException 
  68.      */
  69.     publicvoid crypt(InputStream in, OutputStream out, int mode) throws IOException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {  
  70.         Cipher cipher = Cipher.getInstance("AES");  
  71.         cipher.init(mode, this.key);  
  72.         int blockSize = cipher.getBlockSize();  
  73.         int outputSize = cipher.getOutputSize(blockSize);  
  74.         byte[] inBytes = newbyte[blockSize];  
  75.         byte[] outBytes = newbyte[outputSize];  
  76.         int inLength = 0;  
  77.         boolean more = true;  
  78.         while (more) {  
  79.             inLength = in.read(inBytes);  
  80.             if (inLength == blockSize) {  
  81.                 int outLength = cipher.update(inBytes, 0, blockSize, outBytes);  
  82.                 out.write(outBytes, 0, outLength);  
  83.             } else {  
  84.                 more = false;  
  85.             }  
  86.         }  
  87.         if (inLength > 0)  
  88.             outBytes = cipher.doFinal(inBytes, 0, inLength);  
  89.         else
  90.             outBytes = cipher.doFinal();  
  91.         out.write(outBytes);  
  92.         out.flush();  
  93.     }  
  94.     publicvoid setKey(Key key) {  
  95.         this.key = key;  
  96.     }  
  97.     public Key getKey() {  
  98.         return key;  
  99.     }  
  100. }  

RSA非對稱加密,解密對稱祕鑰

Java程式碼  收藏程式碼
  1. publicclass RSA {  
  2.     publicstaticfinalint KEYSIZE = 512;  
  3.     private KeyPair keyPair;  
  4.     private Key publicKey;  
  5.     private Key privateKey;  
  6.     /** 
  7.      * 生成祕鑰對 
  8.      * @return 
  9.      * @throws NoSuchAlgorithmException 
  10.      */
  11.     public KeyPair generateKeyPair() throws NoSuchAlgorithmException {  
  12.         KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");  
  13.         SecureRandom random = new SecureRandom();  
  14.         pairgen.initialize(RSA.KEYSIZE, random);  
  15.         this.keyPair = pairgen.generateKeyPair();  
  16.         returnthis.keyPair;  
  17.     }  
  18.     /** 
  19.      * 加密祕鑰 
  20.      * @param key 
  21.      * @return 
  22.      * @throws NoSuchAlgorithmException 
  23.      * @throws NoSuchPaddingException 
  24.      * @throws InvalidKeyException 
  25.      * @throws IllegalBlockSizeException 
  26.      */
  27.     publicbyte[] wrapKey(Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException {  
  28.         Cipher cipher = Cipher.getInstance("RSA");  
  29.         cipher.init(Cipher.WRAP_MODE, this.privateKey);  
  30.         byte[] wrappedKey = cipher.wrap(key);  
  31.         return wrappedKey;  
  32.     }  
  33.     /** 
  34.      * 解密祕鑰 
  35.      * @param wrapedKeyBytes 
  36.      * @return 
  37.      * @throws NoSuchAlgorithmException 
  38.      * @throws NoSuchPaddingException 
  39.      * @throws InvalidKeyException 
  40.      */
  41.     public Key unwrapKey(byte[] wrapedKeyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {  
  42.         Cipher cipher = Cipher.getInstance("RSA");  
  43.         cipher.init(Cipher.UNWRAP_MODE, this.publicKey);  
  44.         Key key = cipher.unwrap(wrapedKeyBytes, "AES", Cipher.SECRET_KEY);  
  45.         return key;  
  46.     }  
  47.     public Key getPublicKey() {  
  48.         return publicKey;  
  49.     }  
  50.     publicvoid setPublicKey(Key publicKey) {  
  51.         this.publicKey = publicKey;  
  52.     }  
  53.     public Key getPrivateKey() {  
  54.         return privateKey;  
  55.     }  
  56.     publicvoid setPrivateKey(Key privateKey) {  
  57.         this.privateKey = privateKey;  
  58.     }  
  59. }  
 轉自:http://redstarofsleep.iteye.com/blog/1171282