浅谈DEs,AES

1. AES加密,相对比较简单,之前已经配置好工具类。

package com.bbguoxue.poetry.util;
import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
 * AES加密器
 * @author Eric_Ni
 *
 */
public class AESEncryptor {

    /**
     * AES加密
     */
    public static String encrypt(String seed, String cleartext) throws Exception {  
        byte[] rawKey = getRawKey(seed.getBytes());  
        byte[] result = encrypt(rawKey, cleartext.getBytes());  
        return toHex(result);  
    }  
      
    /**
     * AES解密
     */
    public static String decrypt(String seed, String encrypted) throws Exception {  
        byte[] rawKey = getRawKey(seed.getBytes());  
        byte[] enc = toByte(encrypted);  
        byte[] result = decrypt(rawKey, enc);  
        return new String(result);  
    }  
 
    private static byte[] getRawKey(byte[] seed) throws Exception {  
        KeyGenerator kgen = KeyGenerator.getInstance("AES");  
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG","Crypto");  
        sr.setSeed(seed);  
        kgen.init(128, sr); // 192 and 256 bits may not be available  
        SecretKey skey = kgen.generateKey();  
        byte[] raw = skey.getEncoded();  
        return raw;  
    }  
 
      
    private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {  
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
        Cipher cipher = Cipher.getInstance("AES");  
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);  
        byte[] encrypted = cipher.doFinal(clear);  
        return encrypted;  
    }  
 
    private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {  
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");  
        Cipher cipher = Cipher.getInstance("AES");  
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);  
        byte[] decrypted = cipher.doFinal(encrypted);  
        return decrypted;  
    }  
 
    public static String toHex(String txt) {  
        return toHex(txt.getBytes());  
    }  
    public static String fromHex(String hex) {  
        return new String(toByte(hex));  
    }  
      
    public static byte[] toByte(String hexString) {  
        int len = hexString.length()/2;  
        byte[] result = new byte[len];  
        for (int i = 0; i < len; i++)  
            result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();  
        return result;  
    }  
 
    public static String toHex(byte[] buf) {  
        if (buf == null)  
            return "";  
        StringBuffer result = new StringBuffer(2*buf.length);  
        for (int i = 0; i < buf.length; i++) {  
            appendHex(result, buf[i]);  
        }  
        return result.toString();  
    }  
    private final static String HEX = "0123456789ABCDEF";  
    private static void appendHex(StringBuffer sb, byte b) {  
        sb.append(HEX.charAt((b>>4)&0x0f)).append(HEX.charAt(b&0x0f));  
    }  
}

这里要注意的是红色行,在android4.X的时候可能出席问题。很多地方都是写SecureRandow.getInstance("SHA1PRNG")

 

2. 使用DES加密

//这个现在有点怕了,也还半知半解

 private static final String DES_EDE     = "DESede/ECB/NoPadding";               //定义 加密算法,可用 DES,DESede,Blowfish        //keybyte为加密密钥,长度为24字节    //src为被加密的数据缓冲区(源)  
 
    private static final String DES_EDE_CBC = "DESede/CBC/NoPadding";               //定义 加密算法,可用 DES,DESede,Blowfish        //keybyte为加密密钥,长度为24字节    //src为被加密的数据缓冲区(源)  
 
    private static final String DES_CBC     = "DES/CBC/NoPadding";  
 
    private static final String DES_ECB     = "DES/ECB/PKCS5Padding";  

// 还有"DES/CBC/PKCS5Padding"------------android常用

加密说明: 算法/工作模式/填充

主要涉及的几个问题:工作模式(如上:DES,DESede ...)、填充模式(PKCS5Padding, PKCS7Padding)、初始化向量(如下IvParameterSpec 这个东西容易出问题,注意很多地方初始化0000000,和12345678,这个东西只要有一位不同得到的结果肯定不同)

这几个变量如果你不指定的话,那么就要程序就要调用默认实现,java,android,iso。默认得到的结果肯定不同。

android可用模式,Ios去掉PKCS7Padding的方式得到的结果一样,能通用(Java中只能使用PKCS5Padding)

    private static String encrypt(byte[] raw, byte[] clear) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(ivs);
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "DES");
        Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, zeroIv);
        byte[] encrypted = cipher.doFinal(clear);
        return toHex(encrypted);
    }

//走的弯路

1. 类似AES那样生成密钥key。

2. 使用DESkey

        DESKeySpec dks = new DESKeySpec(raw);
        
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
      //key的长度不能够小于8位字节
        Key secretKey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(new byte[8]);
        AlgorithmParameterSpec paramSpec = iv;
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
        return cipher.doFinal(clear);

得到的结果总不对。可以和上面的比较一下,这个使用了DESKeySpec(这貌似用在ECB模式下),上面直接用的简单的SecretKeySpec。 本来也应该这样用的额,但互通性来说大家都简单的写了。

3. IvParameterSpec 这个类是很重要的, 这玩意是个初始化变量

很多地方可能使用示例new IvParamterSpec("12345678".getBytes()) ---------这其实在正常使用过程中常出现问题

很多都是用默认的{0,0,0,0,0,0,0,0}数组

 

 

 

 我的整个代码

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * AES加密器
 * 
 * @author Eric_Ni
 *
 */
public class AESEncryptor {
    public static void main(String[] args) {
        try {
            System.out.println(encryptDES("123456", "dfardfsf"));
            System.out.println(encrypt("dfardfsf", "123456"));
            System.out.println(decrypt("dfardfsf", "B8CF276AF590D8B9"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * AES加密
     */
    public static String encrypt(String seed, String cleartext)
            throws Exception {
        return encrypt(seed.getBytes(), cleartext.getBytes());
    }

    /**
     * AES解密
     */
    public static String decrypt(String seed, String encrypted)
            throws Exception {
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(seed, enc);
        return new String(result);
    }

    private static byte[] ivs = { 0, 0, 0, 0, 0, 0, 0, 0 };

    public static String encryptDES(String encryptString, String encryptKey)
            throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(new byte[8]);
        SecretKeySpec key = new SecretKeySpec(encryptKey.getBytes(), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key, zeroIv);
        byte[] encryptedData = cipher.doFinal(encryptString.getBytes());

        return toHex(encryptedData);
    }

    private static String encrypt(byte[] raw, byte[] clear) throws Exception {
        IvParameterSpec zeroIv = new IvParameterSpec(ivs);
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, zeroIv);
        byte[] encrypted = cipher.doFinal(clear);
        return toHex(encrypted);
    }

    private static byte[] decrypt(String raw, byte[] encrypted)
            throws Exception {
        SecretKeySpec skeySpec = new SecretKeySpec(raw.getBytes(), "DES");
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
        IvParameterSpec iv = new IvParameterSpec(ivs);
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
        return cipher.doFinal(encrypted);
    }

    public static String toHex(String txt) {
        return toHex(txt.getBytes());
    }

    public static String fromHex(String hex) {
        return new String(hex.getBytes());
    }

    public static byte[] toByte(String hexString) {
        int len = hexString.length() / 2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
                    16).byteValue();
        return result;
    }

    public static String toHex(byte[] buf) {
        if (buf == null)
            return "";
        StringBuffer result = new StringBuffer(2 * buf.length);
        for (int i = 0; i < buf.length; i++) {
            appendHex(result, buf[i]);
        }
        return result.toString();
    }

    private final static String HEX = "0123456789ABCDEF";

    private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
    }
}

 

JAVA中基本就只用这种了,如果需要使用其他的可以参考如下文章,未测试。

 

 

最后分享一下一位兄弟的总结,太多了没想去详细看

主要搞android,太复杂了还是用c做比较好点。不然容易被反编译

1.Base64
  加密:org.apache.commons.codec.binary.Base64.encodeBase64(byte[] binaryData)
  解密:org.apache.commons.codec.binary.Base64.decodeBase64(byte[] base64Data)
2.Md5
  加密:org.apache.commons.codec.digest.md5Hex(byte[] data)
  解密:无
3.DES(des-ecb,3des,des-cbc,cbc-mac)
view plaincopy to clipboardprint?
 import java.io.ByteArrayOutputStream;  
import java.security.SecureRandom;  
import java.util.Arrays;  
 
import javax.crypto.Cipher;  
import javax.crypto.SecretKey;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.DESKeySpec;  
import javax.crypto.spec.DESedeKeySpec;  
import javax.crypto.spec.IvParameterSpec;  
import javax.crypto.spec.SecretKeySpec;  
 
import org.bouncycastle.crypto.BlockCipher;  
import org.bouncycastle.crypto.Mac;  
import org.bouncycastle.crypto.engines.DESEngine;  
import org.bouncycastle.crypto.macs.CBCBlockCipherMac;  
import org.bouncycastle.crypto.params.KeyParameter;  
 
import com.alibaba.common.lang.StringUtil;  
import com.huateng.commons.lang.convert.HexUtils;  
 
public class ShfftDes {  
    //验证用密钥  
    private byte[]              key         = "000000000000000000000000".getBytes();  
 
    //    private byte[]              key         = Hex.decode("00000000");  
 
    private byte[]              ivs         = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };  
 
    private static final String DES_EDE     = "DESede/ECB/NoPadding";               //定义 加密算法,可用 DES,DESede,Blowfish        //keybyte为加密密钥,长度为24字节    //src为被加密的数据缓冲区(源)  
 
    private static final String DES_EDE_CBC = "DESede/CBC/NoPadding";               //定义 加密算法,可用 DES,DESede,Blowfish        //keybyte为加密密钥,长度为24字节    //src为被加密的数据缓冲区(源)  
 
    private static final String DES_CBC     = "DES/CBC/NoPadding";  
 
    private static final String DES_ECB     = "DES/ECB/PKCS5Padding";  
 
     
    public byte[] CryptByDes(byte[] content, int mode) throws Exception {  
        Cipher cipher = Cipher.getInstance(DES_ECB);  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
        SecretKey secretKey = keyFactory.generateSecret(new DESKeySpec(key));  
        cipher.init(mode, secretKey);  
        return cipher.doFinal(content);  
    }  
 
     
    public byte[] CryptBy3Des(byte[] content, int mode) throws Exception {  
        Cipher cipher = Cipher.getInstance(DES_EDE);  
        SecretKey secretKey = new SecretKeySpec(key, "DESede");  
        cipher.init(mode, secretKey);  
        return cipher.doFinal(content);  
    }  
 
     
    public byte[] CryptByDesCbc(byte[] content, int mode) throws Exception {  
        Cipher cipher = Cipher.getInstance(DES_CBC);  
        SecretKey secureKey = new SecretKeySpec(key, "DES");  
        IvParameterSpec iv = new IvParameterSpec(ivs);  
        cipher.init(mode, secureKey, iv);  
        return cipher.doFinal(HexUtils.fromHex(new String(content)));  
    }  
 
     
    public byte[] CryptBy3DesCbc(byte[] content, int mode) throws Exception {  
        Cipher cipher = Cipher.getInstance(DES_EDE_CBC);  
        SecretKey secureKey = new SecretKeySpec(key, "DESede");  
        IvParameterSpec iv = new IvParameterSpec(ivs);  
        cipher.init(mode, secureKey, iv);  
        return cipher.doFinal(content);  
    }  
 
     
    public byte[] CryptByDesCbcMac(byte[] content) throws Exception {  
        BlockCipher engine = new DESEngine();  
        Mac mac = new CBCBlockCipherMac(engine, 64);  
        byte[] macText = new byte[engine.getBlockSize()];  
        mac.init(new KeyParameter(key));  
        mac.update(Padding(content, 64), 0, content.length);  
        mac.update(content, 0, content.length);  
        mac.doFinal(macText, 0);  
        return macText;  
    }  
 
     
    public byte[] ShFftCryptByDessdsCbc(byte[] content, int mode) throws Exception {  
        byte[] ks1 = HexUtils.fromHex(new String(key));  
        byte[] ks = new byte[24];  
        System.arraycopy(ks1, 0, ks, 0, ks1.length);  
        System.arraycopy(ks1, 0, ks, ks1.length, 8);  
 
        Cipher cipher = Cipher.getInstance(DES_EDE_CBC);  
        SecretKeyFactory keyFactory = null;  
        keyFactory = SecretKeyFactory.getInstance("DESede");  
        SecretKey secretKey = null;  
        secretKey = keyFactory.generateSecret(new DESedeKeySpec(ks));  
        IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });  
        cipher.init(mode, secretKey, iv);  
        return cipher.doFinal(HexUtils.fromHex(new String(content)));  
    }  
 
    public byte[] mac(byte[] content) throws Exception {  
        int len;  
        byte plainData[];  
        byte encryptedData[];  
        len = (content.length / 8 + (content.length % 8 != 0 ? 1 : 0)) * 8;  
        plainData = new byte[len];  
        encryptedData = new byte[8];  
        Arrays.fill(plainData, (byte) 32);  
        System.arraycopy(content, 0, plainData, 0, content.length);  
        SecureRandom sr = new SecureRandom();  
        DESKeySpec dks = new DESKeySpec(key);  
        SecretKeyFactory keyFactory = null;  
        keyFactory = SecretKeyFactory.getInstance("DES");  
        SecretKey secretKey = keyFactory.generateSecret(dks);  
        Cipher cipher = Cipher.getInstance("DES/CBC/NoPadding");  
        IvParameterSpec iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });  
        cipher.init(1, secretKey, iv, sr);  
        System.arraycopy(cipher.doFinal(plainData), len - 8, encryptedData, 0, 8);  
        return encryptedData;  
    }  
 
     
    public byte[] Padding(byte[] content, int block) {  
        int contentLength = content.length;  
        int mod = contentLength % block;  
        if (mod != 0) {  
            int size = contentLength + block - mod;  
            //            String s = new String(content);  
            //            StringUtil.alignLeft(s, size, " ");  
            byte[] s = new byte[size];  
            System.arraycopy(content, 0, s, 0, content.length);  
            for (int i = content.length; i < size; i++) {  
                s[i] = 32;  
            }  
            return s;  
        }  
        return content;  
    }  
 
     
    public String Padding(String content, int block) {  
        int contentLength = content.length();  
        int mod = contentLength % block;  
        if (mod != 0) {  
            int size = contentLength + block - mod;  
            String s = new String(content);  
            StringUtil.alignLeft(s, size, " ");  
            return s;  
        }  
        return content;  
    }  
 
     
    public void println(byte[] bs) {  
        for (byte b : bs) {  
            System.out.print(b + " ");  
        }  
        System.out.println();  
    }  
 
     
    public void printlnByte(byte[] bs) {  
        for (byte b : bs) {  
            if (b < 0) {  
                System.out.print((int) b + 256 + " ");  
            } else {  
                System.out.print(b + " ");  
            }  
        }  
        System.out.println();  
    }  
 
     
    public void printlnByteInt16(byte[] bs) {  
        for (byte b : bs) {  
            System.out.print(Integer.toHexString((int) b) + " ");  
        }  
        System.out.println();  
    }  
 
     
    public String dumpBytes(byte[] bytes) {  
        int i;  
        StringBuffer sb = new StringBuffer();  
        for (i = 0; i < bytes.length; i++) {  
            int n = bytes[i] >= 0 ? bytes[i] : 256 + bytes[i];  
            String s = Integer.toHexString(n);  
            if (s.length() < 2) {  
                s = "0" + s;  
            }  
            if (s.length() > 2) {  
                s = s.substring(s.length() - 2);  
            }  
            sb.append(s);  
        }  
        return sb.toString().toUpperCase();  
        //return new BASE64Encoder().encode(bytes);  
    }  
 
    // 一下程序将每2位16进制整数组装成一个字节  
    private String hexString = "0123456789ABCDEF";  
 
    public byte[] decode(String bytes) {  
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);  
        for (int i = 0; i < bytes.length(); i += 2)  
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes  
                .charAt(i + 1))));  
        return baos.toByteArray();  
    }  
 
    public byte[] getKey() {  
        return key;  
    }  
 
    public void setKey(byte[] key) {  
        this.key = key;  
    }  
 
    public byte[] getIvs() {  
        return ivs;  
    }  
 
    public void setIvs(byte[] ivs) {  
        this.ivs = ivs;  
    }  
 
} 
 

 

posted @ 2014-12-27 00:50  pandans  阅读(2790)  评论(0编辑  收藏  举报