zoukankan      html  css  js  c++  java
  • 浅谈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;  
        }  
     
    } 
     
  • 相关阅读:
    P5362 [SDOI2019]连续子序列 思维题
    P5360 [SDOI2019]世界地图 虚树+最小生成树
    P4565 [CTSC2018]暴力写挂 边分治+虚树
    BZOJ2870. 最长道路tree 并查集/边分治
    P4103 [HEOI2014]大工程 虚树
    P4220 [WC2018]通道 虚树+边分治
    P3261 [JLOI2015]城池攻占 可并堆
    积水问题
    23. 合并K个排序链表
    21. 合并两个有序链表
  • 原文地址:https://www.cnblogs.com/pandans/p/4187911.html
Copyright © 2011-2022 走看看