漫谈Java加密技术(二)

本文详细介绍DES数据加密标准算法,包括其工作原理、密钥及数据处理过程,并提供Java实现示例,展示了如何进行加密和解密操作。
接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法。

    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代码实现如下

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安全编码组件  author by 
http://www.bt285.cn http://www.5a520.cn
 *   
 * <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对字符串加密生成密钥,这是比较常见的密钥生成方式。

    再给出一个测试类:

import static org.junit.Assert.*;   
  
import org.junit.Test;   
  
/** *//**  
 *   
 * 
@author by http://www.bt285.cn http://www.5a520.cn 
 * 
@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);就可以了,此外就是密钥长度不同了。

    /**

 * 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
 **/

// 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、付费专栏及课程。

余额充值