• 现代加密体系的各种加密方式


    一、现代加密体系的概览

    二、加密算法介绍

      关于编码和解码,正常的编码是指将字符串转化为特定的编码的二进制,例如,java在内存中使用unicode码,在向外发送数据时,使用不同的编码会将同样的字符串编码成不同的二进制码,如utf-8或gbk。二解码,则是将二进制码根据指定的编码方式,转化成字符串。

      base64编码,跟常用的编码方式是相反的运作,它的编码,是将二进制码转化成字符串;解码则是将字符串转化成二进制码。

    1、base64位加密

      base64中64是指2的6次方,在编码时,会使用6位二进制码表示一个字符。

      base64编码表:

    如图实例:字符串one使用ascii编码后的二进制码,在base64编码后是b25l。

    base64编码,使用6位二进制进行编码,而一个字节有8位二进制。为了能对所有的字节进行编码,且不造成更多的base64字符。采用8和6的最小公倍数,24位二进制位一个单位,也就是说base64编码后的二进制个数是24的整倍数。

    当有空出的字节数时:

    对不能填满6位的二进制补0,完全空出的6位二进制用=代替。如下图:onex的base64编码是b25lfA==

    base64加密实现——java:

    在java的加密体系中,常规加密有三种支持,jdk自带的相关包,bouncy Castle对jdk的补充提供更强的加密强度,Commons Codec是apache提供的安全支持,它一般只是对jdk实现的扩展,比如jdk实现md2和md5算法,Commons Codec也只有md2和md5的实现。实际使用中可以根据需要选择bouncy Castle或Commons Codec。

    package com.tsinkai.ettp.practice;
    
    import java.io.IOException;
    
    import org.apache.commons.codec.binary.Base64;
    
    import sun.misc.BASE64Decoder;
    import sun.misc.BASE64Encoder;    
    
    public class Base64Pra {
        
        private static String src = "hello world!";
        
        public static void main(String[] args) {
            jdkBase64();
            commonsCodesBase64();
            bouncyCastleBase64();
        }
        
        /**
         * jdk自带的base64编码,需要在eclipse里打开相应的包,jdk内部使用,不建议使用。
         */
        public static void jdkBase64() {
            
            try {
                //编码
                BASE64Encoder  encoder = new BASE64Encoder();
                String encodeStr = encoder.encode(src.getBytes());
                System.out.println("jdk encode:" + encodeStr);
                //解码
                BASE64Decoder decoder = new BASE64Decoder();
                System.out.println("jdk decode:"+new String(decoder.decodeBuffer(encodeStr)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        /**
         * commonsCodes中的base64编码
         */
        public static void commonsCodesBase64() {
            //编码
             byte[] encodeBytes = Base64.encodeBase64(src.getBytes());
             String baseStr = Base64.encodeBase64String(src.getBytes());
             System.out.println("cc encode:" + new String(encodeBytes)+"||"+baseStr);
             
             //解码
             byte[] decodeBytes = Base64.decodeBase64(encodeBytes);
             System.out.println("cc decode:" + new String(decodeBytes));
        }
        
        /**
         * bouncyCastle中的base64编码
         */
        public static void bouncyCastleBase64() {
            //编码
            byte[] encodeBatys =  org.bouncycastle.util.encoders.Base64.encode(src.getBytes());
            System.out.println("bc encode:" + new String(encodeBatys));
            
            //解码
            System.out.println("bc decode:" + new String(org.bouncycastle.util.encoders.Base64.decode(encodeBatys)));
        }
    }

     2、消息摘要算法

      消息摘要算法是一种验证消息完整性的算法,它通过一个单向hash加密函数,把字符串加密成固定长度的bit位,不同的字符串产生的输出不同,同样的字符串输出一定相同。同时它是单向加密,不能解密。但是,消息摘要有一定的碰撞率,即不同的明文可能产生相同的密文。

      在验证消息完整性时,只需要将明文字符串使用相同的摘要算法加密,跟接收到的密文进行对比,即可验证消息摘要的完整性。它是数字签名的核心算法。

      MD5和SHA1的算法已经被破解。

    消息摘要的三类实现:

    MD(Message Digest)

    SHA(Secure Hash Algorithm)

    MAC(Message Authentication Code)

    a、MD算法

     MD算法的实现——java:

    package com.tsinkai.ettp.practice;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.bouncycastle.crypto.Digest;
    import org.bouncycastle.crypto.digests.MD2Digest;
    import org.bouncycastle.crypto.digests.MD4Digest;
    import org.bouncycastle.crypto.digests.MD5Digest;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class MDPra {
        
        private static String src = "hello world";
        
        public static void main(String[] args) {
            jdkMD2();
            jdkMD5();
            
            bcMD2();
            bcMD4();
            bcMD5ForProvider();
            bcMD4ForProvider();
            
            ccMD2();
            ccMD5();
        }
        
        //JDK实现MD2
        public static void jdkMD2() {
            try {
                MessageDigest md = MessageDigest.getInstance("MD2");
                byte[] md2bytes = md.digest(src.getBytes());
                //字节数组输出要先转成16进制,可以借助HEX类转换
                System.out.println("JDK MD2:" + Hex.encodeHexString(md2bytes));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        
        //JDK实现MD5
        public static void jdkMD5() {
            try {
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] md5bytes = md.digest(src.getBytes());
                //字节数组输出要先转成16进制,可以借助HEX类转换
                System.out.println("JDK MD5:" + Hex.encodeHexString(md5bytes));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        
        //Bouncy Castle实现MD2
        public static void bcMD2() {
            Digest digest = new MD2Digest();
            digest.update(src.getBytes(), 0, src.getBytes().length); 
            byte[] MD2Bytes = new byte[digest.getDigestSize()];
            digest.doFinal(MD2Bytes, 0);
            System.out.println("BC MD2:" + org.bouncycastle.util.encoders.Hex.toHexString(MD2Bytes));
        }
        
        //Bouncy Castle实现MD4
        public static void bcMD4() {
            Digest digest = new MD4Digest();
            digest.update(src.getBytes(), 0, src.getBytes().length);
            byte[] MD4Bytes = new byte[digest.getDigestSize()];
            digest.doFinal(MD4Bytes, 0);
            System.out.println("BC MD4:" + org.bouncycastle.util.encoders.Hex.toHexString(MD4Bytes));
        }
        //通过设置provider,使用jdk的包调用bouncyCastle的实现,MD5
        //该种方式的provider是sun,若是使用该方式调用MD4,则实现则是BC
        public static void bcMD5ForProvider() {
            
            try {
                Security.addProvider(new BouncyCastleProvider());
                MessageDigest md = MessageDigest.getInstance("MD5");
                System.err.println("JDKforProvider MD5:"+md.getProvider());
                byte[] md5bytes = md.digest(src.getBytes());
                //字节数组输出要先转成16进制,可以借助HEX类转换
                System.out.println("BC MD5ForProvider:" + Hex.encodeHexString(md5bytes));
                
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        //通过设置provider,使用jdk的包调用bouncyCastle的实现,MD4
        public static void bcMD4ForProvider() {
                
                try {
                    Security.addProvider(new BouncyCastleProvider());
                    MessageDigest md = MessageDigest.getInstance("MD4");
                    System.err.println("JDKforProvider MD4:"+md.getProvider());
                    byte[] md5bytes = md.digest(src.getBytes());
                    //字节数组输出要先转成16进制,可以借助HEX类转换
                    System.out.println("BC MD4ForProvider:" + Hex.encodeHexString(md5bytes));
                    
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
        //Commons Codes实现MD2
        public static void ccMD2() {
            System.out.println("CC MD2:"+ DigestUtils.md2Hex(src.getBytes()));
        }
        
        //Commons Codes实现MD5
        public static void ccMD5() {
            System.out.println("CC MD5:"+ DigestUtils.md5Hex(src.getBytes()));
        }
    }

     b.SHA算法

      相比于md5,相近的字符串加密后的密文区别很大。

      sha共有5中算法,一般般sha-1外的算法称为sha-2

    算法 摘要长度 实现方
    SHA-1 160 JDK、CC、BC
    SHA-224 224 BC
    SHA-256 256 JDK、CC、BC
    SHA-384 384 JDK、CC、BC
    SHA-512 512 JDK、CC、BC
    package com.tsinkai.ettp.practice;
    
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.security.Security;
    
    import org.apache.commons.codec.binary.Hex;
    import org.apache.commons.codec.digest.DigestUtils;
    import org.bouncycastle.crypto.Digest;
    import org.bouncycastle.crypto.digests.SHA1Digest;
    import org.bouncycastle.crypto.digests.SHA224Digest;
    import org.bouncycastle.crypto.digests.SHA256Digest;
    import org.bouncycastle.crypto.digests.SHA384Digest;
    import org.bouncycastle.crypto.digests.SHA3Digest;
    import org.bouncycastle.crypto.digests.SHA512Digest;
    import org.bouncycastle.jcajce.provider.digest.SHA3;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class SHAPra {
        private static String src = "hello world!";
        
        public static void main(String[] args) {
            jdkSHA1();
            bcSHA();
            ccSha();
        }
        
        /**
         * jdk实现方式
         */
        public static void jdkSHA1() {
            try {
                //getInstance("SHA-1")该参数可填列表:MD2, MD5, SHA-1, SHA-224, SHA-256, SHA-384, SHA-512
                //填写SHA等同于SHA-1
                MessageDigest md = MessageDigest.getInstance("SHA");//默认调用jdk实现:sun.security.provider.SHA
    //            MessageDigest md = MessageDigest.getInstance("SHA224");//默认调用bc实现:org.bouncycastle.jcajce.provider.digest.SHA224
    //            MessageDigest md = MessageDigest.getInstance("SHA256");//默认调用bc实现:org.bouncycastle.jcajce.provider.digest.SHA256
    //            MessageDigest md = MessageDigest.getInstance("SHA384");//默认调用bc实现:org.bouncycastle.jcajce.provider.digest.SHA384
    //            MessageDigest md = MessageDigest.getInstance("SHA512");//默认调用bc实现:org.bouncycastle.jcajce.provider.digest.SHA512
    //            md.update(src.getBytes());//使用update后后续方法不需要再添加字节数组
                System.out.println("jdk SHA-1:" + Hex.encodeHexString(md.digest(src.getBytes())));
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
            
        }
        
        /**
         * Bouncy Castle 实现方式
         */
        public static void bcSHA() {
            Digest digest = new SHA1Digest();
    //        Digest digest = new SHA224Digest();
    //        Digest digest = new SHA256Digest();
    //        Digest digest = new SHA384Digest();
    //        Digest digest = new SHA512Digest();
            digest.update(src.getBytes(),0,src.getBytes().length);
            System.out.println(digest.getDigestSize());
            byte[] sha1Bytes = new byte[digest.getDigestSize()];
            digest.doFinal(sha1Bytes, 0);
            System.out.println("bc sha-1:" + org.bouncycastle.util.encoders.Hex.toHexString(sha1Bytes));
        }
        
        /**
         * Commons condc实现方式
         */
        public static void ccSha() {
            System.out.println("cc sha1:" + DigestUtils.sha1Hex(src));//改方法底层仍是调用MessageDigest.getInstance("SHA-1");
            System.out.println("CC SHA256:"+DigestUtils.sha256Hex(src));
            System.out.println("CC SHA384:"+DigestUtils.sha384Hex(src));
            System.out.println("CC SHA512:"+DigestUtils.sha512Hex(src));
            
        }
    }

     c、mac——带有秘钥的摘要算法

    package com.tsinkai.ettp.practice;
    
    import javax.crypto.KeyGenerator;
    import javax.crypto.Mac;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.commons.codec.binary.Hex;
    import org.bouncycastle.crypto.digests.MD5Digest;
    import org.bouncycastle.crypto.macs.HMac;
    import org.bouncycastle.crypto.params.KeyParameter;
    
    public class HMacPra {
        
        public static String src = "hello world";
        
        public static void main(String[] args) {
            jdkHMacMD5();
            bcHMacMD5();
        }
        
        public static void jdkHMacMD5() {
            try {
                //获得jdk默认实现的秘钥
                KeyGenerator keyGenerator = KeyGenerator.getInstance("HmacMD5");
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] key = secretKey.getEncoded();
                //可以自定义生成,必须是偶数位
    //            byte[] key = Hex.decodeHex(new char[] {'a','a','a','a','a','a','a','a'});
                
                
                SecretKey restreSecretKey = new SecretKeySpec(key, "HmacMD5");//该步骤是为了生成一个符合HMacMD5的秘钥
                Mac mac = Mac.getInstance(restreSecretKey.getAlgorithm());
                mac.init(restreSecretKey);
                byte[] hmacMD5Bytes = mac.doFinal(src.getBytes());
                System.out.println("jdk hmacMD5:"+Hex.encodeHexString(hmacMD5Bytes));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        public static void bcHMacMD5() {
            HMac hmac = new HMac(new MD5Digest());
            hmac.init(new KeyParameter(org.bouncycastle.util.encoders.Hex.decode("123456")));
            hmac.update(src.getBytes(),0,src.getBytes().length);
            
            byte[] hMacMD5bytes = new byte[hmac.getMacSize()];
            hmac.doFinal(hMacMD5bytes, 0);
            
            System.out.println("bc hmacMD5:" + Hex.encodeHexString(hMacMD5bytes));
        }
    }

    3、对称加密算法

      加密和解密使用相同的秘钥。

     a、DES加密

      

    package com.tsinkai.ettp.practice;
    
    import java.security.Security;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.SecretKeyFactory;
    import javax.crypto.spec.DESKeySpec;
    
    import org.apache.commons.codec.binary.Base64;
    import org.bouncycastle.jce.provider.BouncyCastleProvider;
    
    public class DESPra {
        public static String src = "hello";
        public static void main(String[] args) {
            jdkDES();
            bcDES();
        }
        
        public static void jdkDES() {
            try {
                //生成key
                KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");
                keyGenerator.init(56);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] key = secretKey.getEncoded();
                
                //转化key
                DESKeySpec desKeySpec = new DESKeySpec(key);
                SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
                SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
                
                //加密
                Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("jdk DES encrypt:" + Base64.encodeBase64String(result));
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
                result = cipher.doFinal(result);
                System.out.println("jdk des decrypy:" + new String(result));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
        }
        
        public static void bcDES() {
            //2种方式1、使用setprovider方式,2、使用bc原生的方式
    
            try {
                Security.addProvider(new BouncyCastleProvider());
                //生成key
                KeyGenerator keyGenerator = KeyGenerator.getInstance("DES","BC");//通过参数指定使用provider
                System.out.println(keyGenerator.getProvider());
                keyGenerator.init(56);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] key = secretKey.getEncoded();
                
                //转化key
                DESKeySpec desKeySpec = new DESKeySpec(key);
                SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
                SecretKey convertSecretKey = factory.generateSecret(desKeySpec);
                
                //加密
                Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, convertSecretKey);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("bc DES encrypt:" + Base64.encodeBase64String(result));
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, convertSecretKey);
                result = cipher.doFinal(result);
                System.out.println("bc des decrypy:" + new String(result));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } 
        
        }
    }

    b、AES加密

      

    package com.tsinkai.ettp.practice;
    
    import java.security.Key;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    
    import org.apache.commons.codec.binary.Base64;
    
    public class AESPra {
        public static String src = "hello";
        
        public static void main(String[] args) {
            jdkAES();
        }
        
        public static void jdkAES() {
            try {
                KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
                keyGenerator.init(128);
                SecretKey secretKey = keyGenerator.generateKey();
                byte[] keyBytes = secretKey.getEncoded();
                System.out.println("key0:" + Base64.encodeBase64String(keyBytes));
                //key转化
                Key key = new SecretKeySpec(keyBytes, "AES");
                System.out.println("key:" + Base64.encodeBase64String(key.getEncoded()));
                //加密
                Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, key);
                byte[] result = cipher.doFinal(src.getBytes());
                System.out.println("加:" + result.length);
                System.out.println("jdk AES encrypt:"+Base64.encodeBase64String(result));
                
                //解密
                cipher.init(Cipher.DECRYPT_MODE, key);
                System.out.println("解:"+Base64.decodeBase64(Base64.encodeBase64String(result)).length);
                result = cipher.doFinal(Base64.decodeBase64(Base64.encodeBase64String(result)));
                System.out.println("jdk AES decrypt:" + new String(result));
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        
    }
    就算这个世道烂成一堆粪坑,那也不是你吃屎的理由
  • 相关阅读:
    Tomcat/ WebSphere/WebLogic的作用和特点
    Servlet 执行时一般实现哪几个方法?
    synchronized 和 java.util.concurrent.locks.Lock 的异同 ?
    Request 对象的主要方法
    char 型变量中能不能存贮一个中文汉字?为什么?
    描述一下 JVM 加载 class 文 件的原理机制?
    单例设计模式
    Thread和Runnable
    Math.round方法、String实例化
    思路清晰的秘诀:结构化思维(自上而下)
  • 原文地址:https://www.cnblogs.com/whalesea/p/11353633.html
Copyright © 2020-2023  润新知