各种Java加密算法二

DES 
DES-Data Encryption Standard,即数据加密算法。是IBM公司于1975年研究成功并公开发表的。DES算法的入口参数有三个:Key、Data、Mode。其中 Key为8个字节共64位,是DES算法的工作密钥;Data也为8个字节64位,是要被加密或被解密的数据;Mode为DES的工作方式,有两种:加密 或解密。 
        DES算法把64位的明文输入块变为64位的密文输出块,它所使用的密钥也是64位。 


通过java代码实现如下:Coder类见

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import  java.security.Key;
import  java.security.SecureRandom;
 
import  javax.crypto.Cipher;
import  javax.crypto.KeyGenerator;
import  javax.crypto.SecretKey;
import  javax.crypto.SecretKeyFactory;
import  javax.crypto.spec.DESKeySpec;
 
 
/**
  * DES安全编码组件
 
  * <pre>
  * 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)
  * DES                  key size must be equal to 56
  * DESede(TripleDES)     key size must be equal to 112 or 168
  * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
  * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
  * RC2                  key size must be between 40 and 1024 bits
  * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
  * 具体内容 需要关注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html
  * </pre>
 
  * @author 梁栋
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  DESCoder  extends  Coder {
     /**
      * ALGORITHM 算法 <br>
      * 可替换为以下任意一种算法,同时key值的size相应改变。
     
      * <pre>
      * DES                  key size must be equal to 56
      * DESede(TripleDES)     key size must be equal to 112 or 168
      * AES                  key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
      * Blowfish          key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
      * RC2                  key size must be between 40 and 1024 bits
      * RC4(ARCFOUR)      key size must be between 40 and 1024 bits
      * </pre>
     
      * 在Key toKey(byte[] key)方法中使用下述代码
      * <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 替换
      * <code>
      * DESKeySpec dks = new DESKeySpec(key);
      * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
      * SecretKey secretKey = keyFactory.generateSecret(dks);
      * </code>
      */
     public  static  final  String ALGORITHM =  "DES" ;
 
     /**
      * 转换密钥<br>
     
      * @param key
      * @return
      * @throws Exception
      */
     private  static  Key toKey( byte [] key)  throws  Exception {
         DESKeySpec dks =  new  DESKeySpec(key);
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
         SecretKey secretKey = keyFactory.generateSecret(dks);
 
         // 当使用其他对称加密算法时,如AES、Blowfish等算法时,用下述代码替换上述三行代码
         // SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);
 
         return  secretKey;
     }
 
     /**
      * 解密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] decrypt( byte [] data, String key)  throws  Exception {
         Key k = toKey(decryptBASE64(key));
 
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.DECRYPT_MODE, k);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 加密
     
      * @param data
      * @param key
      * @return
      * @throws Exception
      */
     public  static  byte [] encrypt( byte [] data, String key)  throws  Exception {
         Key k = toKey(decryptBASE64(key));
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.ENCRYPT_MODE, k);
 
         return  cipher.doFinal(data);
     }
 
     /**
      * 生成密钥
     
      * @return
      * @throws Exception
      */
     public  static  String initKey()  throws  Exception {
         return  initKey( null );
     }
 
     /**
      * 生成密钥
     
      * @param seed
      * @return
      * @throws Exception
      */
     public  static  String initKey(String seed)  throws  Exception {
         SecureRandom secureRandom =  null ;
 
         if  (seed !=  null ) {
             secureRandom =  new  SecureRandom(decryptBASE64(seed));
         else  {
             secureRandom =  new  SecureRandom();
         }
 
         KeyGenerator kg = KeyGenerator.getInstance(ALGORITHM);
         kg.init(secureRandom);
 
         SecretKey secretKey = kg.generateKey();
 
         return  encryptBASE64(secretKey.getEncoded());
     }
}


延续上一个类的实现,我们通过MD5以及SHA对字符串加密生成密钥,这是比较常见的密钥生成方式。 
再给出一个测试类:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import  static  org.junit.Assert.*;
 
 
import  org.junit.Test;
 
/**
 
  * @author 梁栋
  * @version 1.0
  * @since 1.0
  */
public  class  DESCoderTest {
 
     @Test
     public  void  test()  throws  Exception {
         String inputStr =  "DES" ;
         String key = DESCoder.initKey();
         System.err.println( "原文:\t"  + inputStr);
 
         System.err.println( "密钥:\t"  + key);
 
         byte [] inputData = inputStr.getBytes();
         inputData = DESCoder.encrypt(inputData, key);
 
         System.err.println( "加密后:\t"  + DESCoder.encryptBASE64(inputData));
 
         byte [] outputData = DESCoder.decrypt(inputData, key);
         String outputStr =  new  String(outputData);
 
         System.err.println( "解密后:\t"  + outputStr);
 
         assertEquals(inputStr, outputStr);
     }
}


得到的输出内容如下:

原文:	DES
密钥:	f3wEtRrV6q0=

加密后:	C6qe9oNIzRY=

解密后:	DES


    由控制台得到的输出,我们能够比对加密、解密后结果一致。这是一种简单的加密解密方式,只有一个密钥。 
    其实DES有很多同胞兄弟,如DESede(TripleDES)、AES、Blowfish、RC2、RC4(ARCFOUR)。这里就不过多阐述了,大同小异,只要换掉ALGORITHM换成对应的值,同时做一个代码替换SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);就可以了,此外就是密钥长度不同了。 

?
1
2
3
4
5
6
7
8
/**
  * DES          key size must be equal to 56
  * DESede(TripleDES) key size must be equal to 112 or 168
  * AES          key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
  * Blowfish     key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
  * RC2          key size must be between 40 and 1024 bits
  * RC4(ARCFOUR) key size must be between 40 and 1024 bits
  **/

    除了DES,我们还知道有DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)等多种对称加密方式,其实现方式大同小异,这里介绍对称加密的另一个算法——PBE 
PBE 
    PBE——Password-based encryption(基于密码加密)。其特点在于口令由用户自己掌管,不借助任何物理媒体;采用随机数(这里我们叫做盐)杂凑多重加密等方法保证数据的安全性。是一种简便的加密方式。 
通过java代码实现如下:Coder类见 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import  java.security.Key;
import  java.util.Random;
  
import  javax.crypto.Cipher;
import  javax.crypto.SecretKey;
import  javax.crypto.SecretKeyFactory;
import  javax.crypto.spec.PBEKeySpec;
import  javax.crypto.spec.PBEParameterSpec;
  
/**
  * PBE安全编码组件
 
  * @author 梁栋
  * @version 1.0
  * @since 1.0
  */
public  abstract  class  PBECoder  extends  Coder {
     /**
      * 支持以下任意一种算法
     
      * <pre>
      * PBEWithMD5AndDES 
      * PBEWithMD5AndTripleDES 
      * PBEWithSHA1AndDESede
      * PBEWithSHA1AndRC2_40
      * </pre>
      */
     public  static  final  String ALGORITHM =  "PBEWITHMD5andDES" ;
  
     /**
      * 盐初始化
     
      * @return
      * @throws Exception
      */
     public  static  byte [] initSalt()  throws  Exception {
         byte [] salt =  new  byte [ 8 ];
         Random random =  new  Random();
         random.nextBytes(salt);
         return  salt;
     }
  
     /**
      * 转换密钥<br>
     
      * @param password
      * @return
      * @throws Exception
      */
     private  static  Key toKey(String password)  throws  Exception {
         PBEKeySpec keySpec =  new  PBEKeySpec(password.toCharArray());
         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
         SecretKey secretKey = keyFactory.generateSecret(keySpec);
  
         return  secretKey;
     }
  
     /**
      * 加密
     
      * @param data 数据
      * @param password 密码
      * @param salt  盐
      * @return
      * @throws Exception
      */
     public  static  byte [] encrypt( byte [] data, String password,  byte [] salt)
             throws  Exception {
  
         Key key = toKey(password);
  
         PBEParameterSpec paramSpec =  new  PBEParameterSpec(salt,  100 );
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
  
         return  cipher.doFinal(data);
  
     }
  
     /**
      * 解密
     
      * @param data  数据
      * @param password 密码
      * @param salt  盐
      * @return
      * @throws Exception
      */
     public  static  byte [] decrypt( byte [] data, String password,  byte [] salt)
             throws  Exception {
  
         Key key = toKey(password);
  
         PBEParameterSpec paramSpec =  new  PBEParameterSpec(salt,  100 );
         Cipher cipher = Cipher.getInstance(ALGORITHM);
         cipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
  
         return  cipher.doFinal(data);
  
     }
}



再给出一个测试类: 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import  static  org.junit.Assert.*;
  
import  org.junit.Test;
  
/**
 
  * @author 梁栋
  * @version 1.0
  * @since 1.0
  */
public  class  PBECoderTest {
  
     @Test
     public  void  test()  throws  Exception {
         String inputStr =  "abc" ;
         System.err.println( "原文: "  + inputStr);
         byte [] input = inputStr.getBytes();
  
         String pwd =  "efg" ;
         System.err.println( "密码: "  + pwd);
  
         byte [] salt = PBECoder.initSalt();
  
         byte [] data = PBECoder.encrypt(input, pwd, salt);
  
         System.err.println( "加密后: "  + PBECoder.encryptBASE64(data));
  
         byte [] output = PBECoder.decrypt(data, pwd, salt);
         String outputStr =  new  String(output);
  
         System.err.println( "解密后: "  + outputStr);
         assertEquals(inputStr, outputStr);
     }
  
}



控制台输出: 

原文: abc
密码: efg
加密后: iCZ0uRtaAhE=
 
解密后: abc
// Java crypt example SJ import javax.crypto.*; import javax.crypto.spec.*; import java.io.*; import java.lang.*; import java.util.*; import java.security.*; public class EncryptionExample { protected String calg = "Blowfish"; // AES. DES, Blowfish protected int keyLen = 128; // 128 for AES, Blowfish, 64 for DES public static void main(String[] args) { EncryptionExample s = new EncryptionExample(); // to call nonstatic methods SecretKeySpec key = s.readkey(); String mess = new String("Hello, world!"); byte[] messb = mess.getBytes(); System.out.println("Plain|" + mess +"|=|" + s.bintohex(messb)); byte[] ct = s.encrypt(messb, key); System.out.println("Encry:" + s.bintohex(ct)); byte[] pt = s.decrypt(ct, key); String dmess = new String(pt); System.out.println("Decry|" + dmess +"|=|" + s.bintohex(pt)); } // main() // encrypt message t with key k public byte[] encrypt(byte[] t, SecretKeySpec k) { try { Cipher c = Cipher.getInstance(calg); c.init(Cipher.ENCRYPT_MODE, k); return c.doFinal(t); } catch (Exception e) { System.err.println("Encryption failed: " + e); } return null; } // decrypt message t with key k public byte[] decrypt(byte[] t, SecretKeySpec k) { try { Cipher c = Cipher.getInstance(calg); c.init(Cipher.DECRYPT_MODE, k); return c.doFinal(t); } catch (Exception e) { System.err.println("Decryption failed: " + e); } return null; } // reads key string from user, returns SecretKeySpec public SecretKeySpec readkey() { SecretKeySpec kp = null; String line; byte [] bin = null; try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.print("Give the key or passphrase (" + keyLen/4 + " hex digits or long ascii string) \n : "); line = in.readLine(); // check if input is all hex or not boolean ishex = true; for (int i = 0; i < line.length(); i++) if (Character.digit(line.charAt(i), 16) < 0) { ishex = false; break; } // check hex key length if (ishex && line.length() != keyLen/4) System.err.println("Wrong hex ley lenght (" + line.length() + "/" + keyLen/4 + ")"); // make binary key if (ishex) bin = hextobin(line); else bin = asciitobin(line); // make key for crypto algorithm kp = new SecretKeySpec(bin, calg); System.out.println("Key = |" + bintohex(kp.getEncoded()) + "|"); } catch (Exception e) { System.err.println("Key generation failed" + e); } return kp; } // readkey() // make binary out of hex string public byte[] hextobin(String s) { int len = (s.length()+1)/2; byte[] A = new byte[len]; for (int i = 0; i < len; i++) A[i] = Integer.valueOf(s.substring(i*2, i*2+2), 16).byteValue(); return A; } // returns new 128 bit key using MD5 of the string s public byte[] asciitobin(String s) { byte[] A = null; try { MessageDigest md = MessageDigest.getInstance("MD5"); A = md.digest(s.getBytes()); } catch (Exception e) { System.err.println("Digest failed" + e); } return A; } // returns new hex string representation of A public String bintohex(byte[] A) { int len = A.length; StringBuffer sb = new StringBuffer(len*2); for (int i = 0; i < len; i++) { if ((A[i] & 0xFF) < 0x10) sb.append("0"); sb.append(Integer.toHexString(A[i] & 0xFF)); } return sb.toString(); } } // class
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值