2021-09-15

加密的理解与应用(Maven,MD5,AES,RSA,Base64)

  • 对称加密和非对称加密的原理

    密码学的来由

    密码的历史极为久远,其起源可以追溯到远古时代。不过有据可查的还是在公元前405年,斯巴达统帅莱桑德将军释读的一封奴隶皮带上的密信。密码在战争中诞生,之后较长的一段时间里,密码学在人们心里一直显得十分神秘。信息技术的发展迅速改变了这一切。随着因特网的普及、计算机和通信技术的迅猛发展,各种机密信息,包括国家安全信息、军事信息、私密信息(如信用卡账号、银行账号)等都需要通过网络进行传输、交换,这些信息关系着国家机密、经济发展和个人稳私等方方面面的安全。但是互联网是一个开放的环境,我们在享受互联网带来便利的同时,也面临着病毒、黑客以及各种各样漏洞的威胁。对信息秘密性和真实性的需求,使得人们对信息安全给予了更多的关注,密码学逐渐揭去了神秘的面纱,走进日常生活当中。 密码学是一门主要研究如何隐秘地传递信息的学科,其首要目的是隐藏信息的涵义,而不是隐藏信息的存在。

    密码学的介绍

    密码学包括密码编码学和密码分析学两个分支。前者是研究密码变化的客观规律,设计各种编码体质对信息进行变换,以保护信息在信道的传递过程中不被敌手窃取、解读和利用;而密码分析学则与密码编码学相反,密码分析学对密码进行分析,在未知密钥的情况下,从密文推出明文或密钥,这是对加密信息进行解密的过程,也就是俗语所说的破解密码,密码分析学主要研究的就是如何分析和破译密码。在整个密码学的发展中,这看似对立的两门学科却是相辅相成、互相促进,推动了密码学一代又一代的发展。 密码学的发展历程大致经历了三个阶段:古代加密方法、古典密码和近代密码。 古代加密方法体现了密码学的若干要素,但只能限制在一定范围内使用。古典密码一般采用手工或机械变换的方式,是以字符为基本加密单元的密码,它比古代加密方法更复杂,但其密钥变化量仍然比较小。

    数据加密的原理

    数据的加密和解密过程都是通过密码体制和密钥来控制的。密码体制的安全性依赖于密钥的安全性,现代密码学不追求加密算法的保密性,而是追求加密算法二点完备,即攻击者在不知道密钥的情况下,没有办法从算法找到突破口。

  • 常用的算法及特点

  • 使用java实现信息加密和解密

    Maven依赖

    如果是使用的是maven工程
    则pom.xml文件需要导入

     		<dependency>
                <groupId>commons-codec</groupId>
                <artifactId>commons-codec</artifactId>
                <version>1.11</version>
            </dependency>
    
    AES 算法
    import java.security.SecureRandom;
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.Charsets;
    import org.apache.commons.codec.binary.Base64;
    import org.apache.commons.codec.binary.Hex;
    
    public class AESEncrypt {
        public static final String KEY_ALGORITHM="AES";
        public static final String CIPHER_ALGORITHM="AES/ECB/PKCS5Padding";
        public static String encrypt(String content, String password) {
            try {
                KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );	            		    secureRandom.setSeed(Base64.encodeBase64(password.getBytes(Charsets.UTF_8)));
                kgen.init(128, secureRandom);
                SecretKey secretKey = kgen.generateKey();
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
                Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 创建密码器
                byte[] byteContent = content.getBytes(Charsets.UTF_8);
                cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
                byte[] result = cipher.doFinal(byteContent);
                return new String(Hex.encodeHex(result,false)) ; // 加密
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        public static String decrypt(String content, String password) {
            try {
                KeyGenerator kgen = KeyGenerator.getInstance(KEY_ALGORITHM);
                SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG" );
                secureRandom.setSeed(Base64.encodeBase64(password.getBytes(Charsets.UTF_8)));
                kgen.init(128, secureRandom);
                SecretKey secretKey = kgen.generateKey();
                byte[] enCodeFormat = secretKey.getEncoded();
                SecretKeySpec key = new SecretKeySpec(enCodeFormat, KEY_ALGORITHM);
                Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);// 创建密码器
                cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
                byte[] result = cipher.doFinal(Hex.decodeHex(content.toCharArray()));
                return new String(result,Charsets.UTF_8); // 加密
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        public static void main(String[] args) {
            String content = "admin";
            String password = "11111 ";
            System.out.println("加密前:" + content);
            String encryptResultStr = encrypt(content, password);
            System.out.println("加密后:" + encryptResultStr);
    
            String decryptResult = decrypt(encryptResultStr, password);
            System.out.println("解密后:" + new String(decryptResult));
        }
    
    }
    
    
    运行结果

    运行结果

    RSA算法
    import org.apache.commons.codec.binary.Base64;
    import javax.crypto.Cipher;
    import java.security.KeyFactory;
    import java.security.KeyPair;
    import java.security.KeyPairGenerator;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.interfaces.RSAPrivateKey;
    import java.security.interfaces.RSAPublicKey;
    import java.security.spec.PKCS8EncodedKeySpec;
    import java.security.spec.X509EncodedKeySpec;
    import java.util.HashMap;
    import java.util.Map;
    
    public class RSAEncrypt {
        private static Map<Integer, String> keyMap = new HashMap<Integer, String>();  //用于封装随机产生的公钥与私钥
        public static void main(String[] args) throws Exception {
            //生成公钥和私钥
            genKeyPair();
            //加密字符串
            String message = "11111";
            System.out.println("随机生成的公钥为:" + keyMap.get(0));
            System.out.println("随机生成的私钥为:" + keyMap.get(1));
            String messageEn = encrypt(message,keyMap.get(0));
            System.out.println(message + "\t加密后的字符串为:" + messageEn);
            String messageDe = decrypt(messageEn,keyMap.get(1));
            System.out.println("还原后的字符串为:" + messageDe);
        }
    
        /**
         * 随机生成密钥对
         * @throws NoSuchAlgorithmException
         */
        public static void genKeyPair() throws NoSuchAlgorithmException {
            // KeyPairGenerator类用于生成公钥和私钥对,基于RSA算法生成对象
            KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
            // 初始化密钥对生成器,密钥大小为96-1024位
            keyPairGen.initialize(1024,new SecureRandom());
            // 生成一个密钥对,保存在keyPair中
            KeyPair keyPair = keyPairGen.generateKeyPair();
            RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
            String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
            // 得到私钥字符串
            String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
            // 将公钥和私钥保存到Map
            keyMap.put(0,publicKeyString);  //0表示公钥
            keyMap.put(1,privateKeyString);  //1表示私钥
        }
    
        public static String encrypt( String str, String publicKey ) throws Exception{
            //base64编码的公钥
            byte[] decoded = Base64.decodeBase64(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            String outStr = Base64.encodeBase64String(cipher.doFinal(str.getBytes("UTF-8")));
            return outStr;
        }
        public static String decrypt(String str, String privateKey) throws Exception{
            //64位解码加密后的字符串
            byte[] inputByte = Base64.decodeBase64(str.getBytes("UTF-8"));
            //base64编码的私钥
            byte[] decoded = Base64.decodeBase64(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            String outStr = new String(cipher.doFinal(inputByte));
            return outStr;
        }
    
    }
    
    
    运行结果

    运行结果

    Base64算法
    import org.apache.commons.codec.binary.Base64;
    public class Base64Coded {
        public static void main(String[] args) {
            String string = "18xinhan2";
            //编码
            String encode = encode(string.getBytes());
            System.out.println(string + "\t编码后的字符串为:" + encode);
            //解码
            String decode = decode(encode.getBytes());
            System.out.println(encode + "\t字符串解码后为:" + decode);
        }
        //base64 解码
        public static String decode(byte[] bytes) {
            return new String(Base64.decodeBase64(bytes));
        }
    
        //base64 编码
        public static String encode(byte[] bytes) {
            return new String(Base64.encodeBase64(bytes));
        }
    }
    
    
  • 实现文件完整性校验

    如何验证数据完整性
    利用md5算法进行验证数据完整性
    md5sum -c 指纹文件命令执行原理
    第一个历程: 打开一个指纹文件,将信息记录到缓存中
    第二个历程: 根据指纹文件的路径信息,生成md5数值信息
    第三个历程: 将新生成md5数值和原有指纹文件中的数值进行比较
    第四个历程: 如果相同显示结果为ok,如果不同显示failed

    
    import java.security.MessageDigest;
    import java.io.FileInputStream;
    import java.io.InputStream;
    
    public class MD5 {
        private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
                '9','A', 'B', 'C', 'D', 'E', 'F' };
    
        public static void main(String[] args)
        {
            System.out.println(md5sum("/init.rc"));
        }
    
        public static String toHexString(byte[] b) {
            StringBuilder stringBuilder = new StringBuilder(b.length * 2);
            for (int i = 0; i < b.length; i++) {
                stringBuilder.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);
                stringBuilder.append(HEX_DIGITS[b[i] & 0x0f]);
            }
            return stringBuilder.toString();
        }
    
        public static String md5sum(String filePath) {
            InputStream fis;
            byte[] buffer = new byte[1024];
            int numRead = 0;
            MessageDigest md5;
            try{
                fis = new FileInputStream(filePath);
                md5 = MessageDigest.getInstance("MD5");
                while((numRead=fis.read(buffer)) > 0) {
                    md5.update(buffer,0,numRead);
                }
                fis.close();
                return toHexString(md5.digest());
            } catch (Exception e) {
                System.out.println("error");
                return null;
            }
        }
    }
    
    
    

小结:

MD5方法在十年后的今天已经有了很多的计算及应用,但是随着时间的推移,常用的数字形式及数字的排列顺序已记录在库,使网上出现许多的MD5的解码网站,更多的撞库次数使其不再安全.调用方法基本可以实现常用的加密方式,使用更完备的函数来实现新型的加密方式,是我们之后要学习的地方

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值