加密的理解与应用(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,如果不同显示failedimport 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的解码网站,更多的撞库次数使其不再安全.调用方法基本可以实现常用的加密方式,使用更完备的函数来实现新型的加密方式,是我们之后要学习的地方