加解密算法總結(RSA,DES,MD5)

一.非對稱加密算法RSA

  非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)。公開密鑰與私有密鑰是一對,如果用公開密鑰對數據進行加密,只有用對應的私有密鑰才能解密;如果用私有密鑰對數據進行加密,那麼只有用對應的公開密鑰才能解密。因爲加密和解密使用的是兩個不同的密鑰,所以這種算法叫作非對稱加密算法。RSA算法實現如下:

  1 import java.io.ByteArrayOutputStream;
  2 import java.security.Key;
  3 import java.security.KeyFactory;
  4 import java.security.KeyPair;
  5 import java.security.KeyPairGenerator;
  6 import java.security.interfaces.RSAPrivateKey;
  7 import java.security.interfaces.RSAPublicKey;
  8 import java.security.spec.PKCS8EncodedKeySpec;
  9 import java.security.spec.X509EncodedKeySpec;
 10 import java.util.HashMap;
 11 import java.util.Map;
 12 
 13 import javax.crypto.Cipher;
 14 
 15 import sun.misc.BASE64Decoder;
 16 import sun.misc.BASE64Encoder;
 17 
 18 public class RSAUtils {
 19     
 20 
 21     /**默認編碼*/
 22     private final static String DEFAULT_CHARSET = "UTF-8";
 23 
 24     /** *//** 
 25      * RSA最大加密明文大小 
 26      */  
 27     private static final int MAX_ENCRYPT_BLOCK = 117;  
 28       
 29     /** *//** 
 30      * RSA最大解密密文大小 
 31      */  
 32     private static final int MAX_DECRYPT_BLOCK = 128; 
 33     
 34     /**
 35      * BASE64解密
 36      * @param key
 37      * @return
 38      * @throws Exception
 39      */
 40     public static byte[] decryptBASE64(String key) throws Exception{
 41         return (new BASE64Decoder()).decodeBuffer(key);
 42     }
 43     
 44     /**
 45      * BASE64加密
 46      * @param key
 47      * @return
 48      * @throws Exception
 49      */
 50     public static String encryptBASE64(byte[] key)throws Exception{
 51         return (new BASE64Encoder()).encodeBuffer(key);
 52     }
 53     
 54     
 55     public static final String KEY_ALGORTHM="RSA";//
 56     public static final String SIGNATURE_ALGORITHM="MD5withRSA";
 57     
 58     public static final String PUBLIC_KEY = "RSAPublicKey";//公鑰
 59     public static final String PRIVATE_KEY = "RSAPrivateKey";//私鑰
 60 
 61 
 62 
 63 
 64 /**
 65      * 初始化密鑰
 66      * @return
 67      * @throws Exception
 68      */
 69     public static Map<String,Object> initKey()throws Exception{
 70         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
 71         keyPairGenerator.initialize(1024);
 72         KeyPair keyPair = keyPairGenerator.generateKeyPair();
 73         
 74         //公鑰
 75         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 76         //私鑰
 77         RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();
 78         
 79         Map<String,Object> keyMap = new HashMap<String, Object>(2);
 80         keyMap.put(PUBLIC_KEY, publicKey);
 81         keyMap.put(PRIVATE_KEY, privateKey);
 82         
 83         return keyMap;
 84     }
 85 
 86 /**
 87      * 取得公鑰,並轉化爲String類型
 88      * @param keyMap
 89      * @return
 90      * @throws Exception
 91      */
 92     public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
 93         Key key = (Key) keyMap.get(PUBLIC_KEY);  
 94         return encryptBASE64(key.getEncoded());     
 95     }
 96 
 97     /**
 98      * 取得私鑰,並轉化爲String類型
 99      * @param keyMap
100      * @return
101      * @throws Exception
102      */
103     public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
104         Key key = (Key) keyMap.get(PRIVATE_KEY);  
105         return encryptBASE64(key.getEncoded());     
106     }
107 
108 /**
109      * 用私鑰加密
110      * @param data    加密數據
111      * @param key    密鑰
112      * @return
113      * @throws Exception
114      */
115     public static byte[] encryptByPrivateKey(byte[] data,String key)throws Exception{
116         //解密密鑰
117         byte[] keyBytes = decryptBASE64(key);
118         //取私鑰
119         PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
120         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
121         Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
122         
123         //對數據加密
124         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
125         cipher.init(Cipher.ENCRYPT_MODE, privateKey);
126         
127         int inputLen = data.length;  
128         ByteArrayOutputStream out = new ByteArrayOutputStream();  
129         int offSet = 0;  
130         byte[] cache;  
131         int i = 0;  
132         // 對數據分段加密  
133         while (inputLen - offSet > 0) {  
134             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  
135                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  
136             } else {  
137                 cache = cipher.doFinal(data, offSet, inputLen - offSet);  
138             }  
139             out.write(cache, 0, cache.length);  
140             i++;  
141             offSet = i * MAX_ENCRYPT_BLOCK;  
142         }  
143         byte[] encryptedData = out.toByteArray();  
144         out.close();  
145         return encryptedData;
146     }
147     
148 
149     /**
150      * 用私鑰加密
151      * @param data    加密數據
152      * @param key    密鑰
153      * @return
154      * @throws Exception
155      */
156     public static String encryptByPrivateKey(String data,String key)throws Exception{
157         
158         return encryptBASE64(encryptByPrivateKey(data.getBytes(DEFAULT_CHARSET), key));
159     }
160     
161     /**
162      * 用私鑰解密
163      * @param data base64
164      * @param key
165      * @return String
166      * @throws Exception
167      */
168     public static String decryptByPrivateKey(String data,String key)throws Exception{
169         
170         return new String(decryptByPrivateKey(decryptBASE64(data), key),DEFAULT_CHARSET);
171     }
172 
173 
174 /**
175      * 用私鑰解密 * @param data     加密數據
176      * @param key    密鑰
177      * @return
178      * @throws Exception
179      */
180     public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
181         //對私鑰解密
182         byte[] keyBytes = decryptBASE64(key);
183         
184         PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
185         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
186         Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
187         //對數據解密
188         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
189         cipher.init(Cipher.DECRYPT_MODE, privateKey);
190         
191         int inputLen = data.length;  
192         ByteArrayOutputStream out = new ByteArrayOutputStream();  
193         int offSet = 0;  
194         byte[] cache;  
195         int i = 0;  
196         // 對數據分段解密  
197         while (inputLen - offSet > 0) {  
198             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {  
199                 cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);  
200             } else {  
201                 cache = cipher.doFinal(data, offSet, inputLen - offSet);  
202             }  
203             out.write(cache, 0, cache.length);  
204             i++;  
205             offSet = i * MAX_DECRYPT_BLOCK;  
206         }  
207         byte[] decryptedData = out.toByteArray();  
208         out.close();  
209         return decryptedData; 
210     }
211 
212 
213     /**
214      * 用公鑰加密
215      * @param data    加密數據
216      * @param key    密鑰
217      * @return
218      * @throws Exception
219      */
220     public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
221         //對公鑰解密
222         byte[] keyBytes = decryptBASE64(key);
223         //取公鑰
224         X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
225         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
226         Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
227         
228         //對數據解密
229         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
230         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
231         
232         int inputLen = data.length;  
233         ByteArrayOutputStream out = new ByteArrayOutputStream();  
234         int offSet = 0;  
235         byte[] cache;  
236         int i = 0;  
237         // 對數據分段加密  
238         while (inputLen - offSet > 0) {  
239             if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {  
240                 cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);  
241             } else {  
242                 cache = cipher.doFinal(data, offSet, inputLen - offSet);  
243             }  
244             out.write(cache, 0, cache.length);  
245             i++;  
246             offSet = i * MAX_ENCRYPT_BLOCK;  
247         }  
248         byte[] encryptedData = out.toByteArray();  
249         out.close();  
250         return encryptedData; 
251     }
252 
253 
254 /**
255      * 用公鑰解密
256      * @param data    加密數據
257      * @param key    密鑰
258      * @return
259      * @throws Exception
260      */
261     public static byte[] decryptByPublicKey(byte[] data,String key)throws Exception{
262         //對私鑰解密
263         byte[] keyBytes = decryptBASE64(key);
264         X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
265         KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
266         Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
267         
268         //對數據解密
269         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
270         cipher.init(Cipher.DECRYPT_MODE, publicKey);
271         
272         int inputLen = data.length;  
273         ByteArrayOutputStream out = new ByteArrayOutputStream();  
274         int offSet = 0;  
275         byte[] cache;  
276         int i = 0;  
277         // 對數據分段解密  
278         while (inputLen - offSet > 0) {  
279             if (inputLen - offSet > MAX_DECRYPT_BLOCK) {  
280                 cache = cipher.doFinal(data, offSet, MAX_DECRYPT_BLOCK);  
281             } else {  
282                 cache = cipher.doFinal(data, offSet, inputLen - offSet);  
283             }  
284             out.write(cache, 0, cache.length);  
285             i++;  
286             offSet = i * MAX_DECRYPT_BLOCK;  
287         }  
288         byte[] decryptedData = out.toByteArray();  
289         out.close();  
290         return decryptedData;
291     }
292 
293     /**
294      * 用公鑰加密
295      * @param data    加密數據
296      * @param key    密鑰
297      * @return
298      * @throws Exception
299      */
300     public static String encryptByPublicKey(String data,String key)throws Exception{
301         
302         return encryptBASE64(encryptByPublicKey(data.getBytes(DEFAULT_CHARSET), key));
303     }
304     
305     /**
306      * 用公鑰解密
307      * @param data base64
308      * @param key
309      * @return String
310      * @throws Exception
311      */
312     public static String decryptByPublicKey(String data,String key)throws Exception{
313         
314         return new String(decryptByPublicKey(decryptBASE64(data), key),DEFAULT_CHARSET);
315     }
316     
317     public static void main(String[] args) throws Exception {
318         
319         Map<String,Object> keyMap = initKey();
320         String publicKey = getPublicKey(keyMap);
321         String privateKey = getPrivateKey(keyMap);
322         
323         String s = "水電費";
324         s = encryptByPrivateKey(s, privateKey);
325         System.out.println("私鑰加密後密文爲:"+s);
326         s = decryptByPublicKey(s, publicKey);
327         System.out.println("公鑰解密後明文爲:"+s);
328 
329     }
330 }
View Code

 

二.對稱加密算法DES

  在對稱加密算法中,數據發信方將明文原始數據和加密密鑰一起經過特殊加密算法處理後,使其變成複雜的加密密文發送出去。收信方收到密文後,若想解讀原文,則需要使用加密用過的密鑰及相同算法的逆算法對密文進行解密,才能使其恢復成可讀明文。在對稱加密算法中,使用的密鑰只有一個,發收信雙方都使用這個密鑰對數據進行加密和解密,這就要求解密方事先必須知道加密密鑰.DES具體實現如下:

  1 import java.security.InvalidKeyException;
  2 import java.security.Key;
  3 import java.security.NoSuchAlgorithmException;
  4 import java.security.SecureRandom;
  5 import java.security.spec.InvalidKeySpecException;
  6 
  7 import javax.crypto.Cipher;
  8 import javax.crypto.SecretKey;
  9 import javax.crypto.SecretKeyFactory;
 10 import javax.crypto.spec.DESKeySpec;
 11 
 12 import com.sun.org.apache.xml.internal.security.utils.Base64;
 13 
 14 public class DESUtil {
 15     //算法名稱 
 16     public static final String KEY_ALGORITHM = "DES";
 17     //算法名稱/加密模式/填充方式 
 18     //DES共有四種工作模式-->>ECB:電子密碼本模式、CBC:加密分組鏈接模式、CFB:加密反饋模式、OFB:輸出反饋模式
 19     public static final String CIPHER_ALGORITHM = "DES/ECB/NoPadding";
 20 
 21     /**
 22      *   
 23      * 生成密鑰key對象
 24      * @param KeyStr 密鑰字符串 
 25      * @return 密鑰對象 
 26      * @throws InvalidKeyException   
 27      * @throws NoSuchAlgorithmException   
 28      * @throws InvalidKeySpecException   
 29      * @throws Exception 
 30      */
 31     private static SecretKey keyGenerator(String keyStr) throws Exception {
 32         byte input[] = HexString2Bytes(keyStr);
 33         DESKeySpec desKey = new DESKeySpec(input);
 34         //創建一個密匙工廠,然後用它把DESKeySpec轉換成
 35         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
 36         SecretKey securekey = keyFactory.generateSecret(desKey);
 37         return securekey;
 38     }
 39 
 40     private static int parse(char c) {
 41         if (c >= 'a') return (c - 'a' + 10) & 0x0f;
 42         if (c >= 'A') return (c - 'A' + 10) & 0x0f;
 43         return (c - '0') & 0x0f;
 44     }
 45 
 46     // 從十六進制字符串到字節數組轉換 
 47     public static byte[] HexString2Bytes(String hexstr) {
 48         byte[] b = new byte[hexstr.length() / 2];
 49         int j = 0;
 50         for (int i = 0; i < b.length; i++) {
 51             char c0 = hexstr.charAt(j++);
 52             char c1 = hexstr.charAt(j++);
 53             b[i] = (byte) ((parse(c0) << 4) | parse(c1));
 54         }
 55         return b;
 56     }
 57 
 58     /** 
 59      * 加密數據
 60      * @param data 待加密數據
 61      * @param key 密鑰
 62      * @return 加密後的數據 
 63      */
 64     public static String encrypt(String data, String key) throws Exception {
 65         Key deskey = keyGenerator(key);
 66         // 實例化Cipher對象,它用於完成實際的加密操作
 67         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
 68         SecureRandom random = new SecureRandom();
 69         // 初始化Cipher對象,設置爲加密模式
 70         cipher.init(Cipher.ENCRYPT_MODE, deskey, random);
 71         byte[] results = cipher.doFinal(data.getBytes());
 72         for (int i = 0; i < results.length; i++) {
 73             System.out.print(results[i] + " ");
 74         }
 75         System.out.println();
 76         // 執行加密操作。加密後的結果通常都會用Base64編碼進行傳輸 
 77         return Base64.encode(results);
 78     }
 79 
 80     /** 
 81      * 解密數據 
 82      * @param data 待解密數據 
 83      * @param key 密鑰 
 84      * @return 解密後的數據 
 85      */
 86     public static String decrypt(String data, String key) throws Exception {
 87         Key deskey = keyGenerator(key);
 88         Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
 89         //初始化Cipher對象,設置爲解密模式
 90         cipher.init(Cipher.DECRYPT_MODE, deskey);
 91         // 執行解密操作
 92         return new String(cipher.doFinal(Base64.decode(data)));
 93     }
 94 
 95     public static void main(String[] args) throws Exception {
 96         String source = "abcde123";
 97         System.out.println("原文: " + source);
 98         String key = "A1B2C3D4E5F60708";
 99         String encryptData = encrypt(source, key);
100         System.out.println("加密後: " + encryptData);
101         String decryptData = decrypt(encryptData, key);
102         System.out.println("解密後: " + decryptData);
103     }
104 }
View Code

 

三.MD5摘要

  MD5即Message-Digest Algorithm 5(信息-摘要算法5),用於確保信息傳輸完整一致。是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流編程語言普遍已有MD5實現。將數據(如漢字)運算爲另一固定長度值,是雜湊算法的基礎原理,MD5具體實現如下:

  1 public class MD5{
  2     /*
  3     *四個鏈接變量
  4     */
  5     private final int A=0x67452301;
  6     private final int B=0xefcdab89;
  7     private final int C=0x98badcfe;
  8     private final int D=0x10325476;
  9     /*
 10     *ABCD的臨時變量
 11     */
 12     private int Atemp,Btemp,Ctemp,Dtemp;
 13      
 14     /*
 15     *常量ti
 16     *公式:floor(abs(sin(i+1))×(2pow32)
 17     */
 18     private final int K[]={
 19         0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
 20         0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
 21         0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
 22         0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
 23         0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
 24         0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
 25         0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
 26         0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
 27         0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
 28         0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
 29         0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
 30         0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
 31         0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
 32     /*
 33     *向左位移數,計算方法未知
 34     */
 35     private final int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
 36         12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
 37         4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
 38         15,21,6,10,15,21,6,10,15,21,6,10,15,21};
 39      
 40      
 41     /*
 42     *初始化函數
 43     */
 44     private void init(){
 45         Atemp=A;
 46         Btemp=B;
 47         Ctemp=C;
 48         Dtemp=D;
 49     }
 50     /*
 51     *移動一定位數
 52     */
 53     private    int    shift(int a,int s){
 54         return(a<<s)|(a>>>(32-s));//右移的時候,高位一定要補零,而不是補充符號位
 55     }
 56     /*
 57     *主循環
 58     */
 59     private void MainLoop(int M[]){
 60         int F,g;
 61         int a=Atemp;
 62         int b=Btemp;
 63         int c=Ctemp;
 64         int d=Dtemp;
 65         for(int i = 0; i < 64; i ++){
 66             if(i<16){
 67                 F=(b&c)|((~b)&d);
 68                 g=i;
 69             }else if(i<32){
 70                 F=(d&b)|((~d)&c);
 71                 g=(5*i+1)%16;
 72             }else if(i<48){
 73                 F=b^c^d;
 74                 g=(3*i+5)%16;
 75             }else{
 76                 F=c^(b|(~d));
 77                 g=(7*i)%16;
 78             }
 79             int tmp=d;
 80             d=c;
 81             c=b;
 82             b=b+shift(a+F+K[i]+M[g],s[i]);
 83             a=tmp;
 84         }
 85         Atemp=a+Atemp;
 86         Btemp=b+Btemp;
 87         Ctemp=c+Ctemp;
 88         Dtemp=d+Dtemp;
 89      
 90     }
 91     /*
 92     *填充函數
 93     *處理後應滿足bits≡448(mod512),字節就是bytes≡56(mode64)
 94     *填充方式爲先加一個0,其它位補零
 95     *最後加上64位的原來長度
 96     */
 97     private int[] add(String str){
 98         int num=((str.length()+8)/64)+1;//以512位,64個字節爲一組
 99         int strByte[]=new int[num*16];//64/4=16,所以有16個整數
100         for(int i=0;i<num*16;i++){//全部初始化0
101             strByte[i]=0;
102         }
103         int    i;
104         for(i=0;i<str.length();i++){
105             strByte[i>>2]|=str.charAt(i)<<((i%4)*8);//一個整數存儲四個字節,小端序
106         }
107         strByte[i>>2]|=0x80<<((i%4)*8);//尾部添加1
108         /*
109         *添加原長度,長度指位的長度,所以要乘8,然後是小端序,所以放在倒數第二個,這裏長度只用了32位
110         */
111         strByte[num*16-2]=str.length()*8;
112             return strByte;
113     }
114     /*
115     *調用函數
116     */
117     public String getMD5(String source){
118         init();
119         int strByte[]=add(source);
120         for(int i=0;i<strByte.length/16;i++){
121         int num[]=new int[16];
122         for(int j=0;j<16;j++){
123             num[j]=strByte[i*16+j];
124         }
125         MainLoop(num);
126         }
127         return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);
128      
129     }
130     /*
131     *整數變成16進制字符串
132     */
133     private String changeHex(int a){
134         String str="";
135         for(int i=0;i<4;i++){
136             str+=String.format("%2s", Integer.toHexString(((a>>i*8)%(1<<8))&0xff)).replace(' ', '0');
137  
138         }
139         return str;
140     }
141     /*
142     *單例
143     */
144     private static MD5 instance;
145     public static MD5 getInstance(){
146         if(instance==null){
147             instance=new MD5();
148         }
149         return instance;
150     }
151      
152     private MD5(){};
153     
154     /**
155      * 加密解密算法 執行一次加密,兩次解密
156      */ 
157     public static String convertMD5(String inStr){
158 
159         char[] a = inStr.toCharArray();
160         for (int i = 0; i < a.length; i++){
161             a[i] = (char) (a[i] ^ 't');
162         }
163         String s = new String(a);
164         return s;
165 
166     }
167 
168     
169     public static void main(String[] args){
170         String s = "abcde";
171         System.out.println("明文:"+s);
172         String str=MD5.getInstance().getMD5(s);
173         System.out.println("MD5值:"+str);
174         System.out.println("加密後:" + convertMD5(str));  
175         System.out.println("解密後:" + convertMD5(convertMD5(str)));
176     }
177 }
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章