赞
踩
Base64编码
严格来说只是一种编码方式,并不算是加密算法
Base64 编码是从二进制到字符的过程,用 64 个字符来表示任意的二进制数据,常用于在 HTTP 加密,图片编码传输等
MD5信息摘要算法
Message Digest algorithm 5
一般用于确保信息的传输完整一致性,校验传输的数据是否被修改,一旦原始信息被修改,生成的 MD5 值将会变得很不同
SHA密码散列函数家族
FIPS 所认证的安全散列算法,和 MD5 类似,都是对文本进行散列,产生一定长度的散列值
HMAC散列消息鉴别码
Hash Message Authentication Code
是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证数据的完整性,同时可以用来作某个消息的身份验证。
对称加密的意思就是信息收发都有相同的一把钥匙,消息的加密解密都用这把钥匙进行。
1、DES
Data Encryption Standard,数据加密标准,速度较快,适用于加密大量数据的场合。
2、3DES
DES的升级版,原理和DES一样,需要处理三个密钥
3、AES
Advanced Encryption Standard,高级加密标准,是下一代的加密算法标准,速度快,安全级别高;
非对称加密算法是一种密钥的保密方法。
非对称加密算法需要两个密钥:
公开密钥(publickey)和私有密钥(privatekey)。
公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有密钥才能解密;如果用私有密钥对数据进行加密,那么只有用对应的公开密钥才能解密。
1、RSA
名称来源于发明这个算法的三个人的姓氏组成,算法大致内容就是对极大整数进行因式分解
这种算法非常可靠,密钥越长,它就越难破解。根据已经披露的文献,目前被破解的最长 RSA密钥是768个二进制位。也就是说,长度超过768位的密钥,还无法破解(至少没人公开宣布)。因此可以认为,1024位的RSA密钥基本安全,2048位的密钥极其安全。
2、DSA
Digital Signature Algorithm,数字签名算法,是一种标准的 DSS(数字签名标准);
3、ECC
Elliptic Curves Cryptography,椭圆曲线密码编码学。
一种建立公开密钥加密的算法,基于椭圆曲线数学。
ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射,基于Weil对或是Tate对;双线性映射已经在密码学中发现了大量的应用,例如基于身份的加密。不过一个缺点是加密和解密操作的实现比其他机制花费的时间长。
现在的加密算法大部分情况下是为了验证数据的一致性,例如传递一些参数组的时候,简单的会使用 BASE64 或 MD5 进行加密生成一个签名。复杂点就是 BASE64 编码之后再用 对称密钥再加密一次,达到比较不容易被人篡改的目的
对于一些支付场景,一般使用非对称加密算法 实现,这样的场景需要的安全性更高。
public static void main(String[] args) throws Exception { String data = "即将加密的数据"; //base64加密(方式1) String encData1 = Base64.encodeBase64String(data.getBytes()); //base64加密(方式2) String encData2 = (new BASE64Encoder()).encodeBuffer(data.getBytes()); System.out.println("encData1 = "+ encData1); System.out.println("encData2 = "+ encData2); //base64解密(方式1) byte[] decData1 = Base64.decodeBase64(encData1); byte[] decData2 = Base64.decodeBase64(encData2); //base64解密(方式2) byte[] decData3 = (new BASE64Decoder()).decodeBuffer(encData1); byte[] decData4 = (new BASE64Decoder()).decodeBuffer(encData2); System.out.println("decData1 = "+ new String(decData1) ); System.out.println("decData2 = "+ new String(decData2) ); System.out.println("decData3 = "+ new String(decData3) ); System.out.println("decData4 = "+ new String(decData4) ); }
public static void main(String[] args) throws Exception {
String data = "即将加密的数据";
// 拿到一个MD5转换器
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(data.getBytes());
BigInteger encData = new BigInteger(md5.digest());
//加密之后转换为16进制字符串
System.out.println("encData = "+ encData.toString(16));
}
public static void main(String[] args) throws Exception {
String data = "即将加密的数据";
// 拿到一个SHA转换器
MessageDigest sha = MessageDigest.getInstance("SHA");
sha.update(data.getBytes());
BigInteger encData = new BigInteger(sha.digest());
//加密之后转换为32进制字符串
System.out.println("encData = "+ encData.toString(32));
}
/** * MAC算法可选以下多种算法 * <pre> * HmacMD5 * HmacSHA1 * HmacSHA256 * HmacSHA384 * HmacSHA512 * </pre> */ public static final String KEY_MAC = "HmacMD5"; public static void main(String[] args) throws Exception { String data = "即将加密的数据"; String key = "给定密钥"; //根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称 SecretKey secretKey = new SecretKeySpec(key.getBytes(), KEY_MAC); //getInstance得到实例 Mac mac = Mac.getInstance(secretKey.getAlgorithm()); //用给定密钥初始化 Mac 对象 mac.init(secretKey); // 加密处理 BigInteger macMd5 = new BigInteger(mac.doFinal(data.getBytes())) System.out.println("HMAC:" + macMd5.toString(16)); }
在对称加密算法中,加密与解密的密钥是相同的。
128 192 256 分别表示密钥的长度。
填充方式:
1、NoPadding
不进行填充,但是这里要求明文必须要是16个字节的整数倍,如果一定要用 NoPadding 的话,那么必须保证原文字节是 8 的倍数,否则的话需要使用其他的填充模式。
2、PKCS5Padding(默认)
在明文的末尾进行填充,填充的数据是当前和16个字节相差的数量,例如:
- 未填充明文
1,2,3,4,5,6,7,8,9,10,11- 填充明文(缺少五个满足16个字节)
1,2,3,4,5,6,7,8,9,10,11,5,5,5,5,5注:使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据
3、 ISO10126Padding
在明文的末尾进行填充,当前和16个字节相差的数量填写在最后,其余字节填充随机数,例如:
- 未填充明文
1,2,3,4,5,6,7,8,9,10,11- 填充明文(缺少五个满足16个字节)
1,2,3,4,5,6,7,8,9,10,11,c,b,4,1,5
模式
模式是需要制定AES对明文进行加密时使用的模式,一共有五种模式,模式的基本原理是相似的,但是细节上会有一些变化。
- ECB模式(默认):电码本模式
- CBC模式:密码分组链接模式
- CFB模式:密码反馈模式
- OFB模式:输出反馈模式
- CTR模式:计算器模式
如果想详细了解内部原理可以参考:
https://www.cnblogs.com/better-farther-world2099/p/13293291.html
https://blog.csdn.net/qq_28205153/article/details/55798628
public static void main(String[] args) throws Exception { /* * 此处使用AES-128-ECB加密模式。 */ String key = "很随便的密钥"; // 需要加密的字串 String data = "即将加密的数据"; // 加密 String encData = encrypt(data, key); System.out.println("加密后的字串是:" + encData); // 解密 String decData = decrypt(encData, key); System.out.println("解密后的字串是:" + decData); } // 加密 public static String encrypt(String data, String key) throws Exception { //创建AES的Key生产者 KeyGenerator kgen = KeyGenerator.getInstance("AES"); // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥 kgen.init(128, new SecureRandom(key.getBytes())); //SecureRandom是生成安全随机数序列 SecretKey secretKey = kgen.generateKey(); byte[] rKey = secretKey.getEncoded(); // 转换为AES专用密钥 SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES"); // 创建密码器 //"算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 初始化为加密模式的密码器 cipher.init(Cipher.ENCRYPT_MODE, skeySpec); byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); //此处使用BASE64做转码功能,同时能起到2次加密的作用。 return new BASE64Encoder().encode(encrypted); } // 解密 public static String decrypt(String encData, String key) throws Exception { //创建AES的Key生产者 KeyGenerator kgen = KeyGenerator.getInstance("AES"); // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥 kgen.init(128, new SecureRandom(key.getBytes())); //SecureRandom是生成安全随机数序列 SecretKey secretKey = kgen.generateKey(); byte[] rKey = secretKey.getEncoded(); SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES"); // 创建密码器 Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); // 初始化为解密模式的密码器 cipher.init(Cipher.DECRYPT_MODE, skeySpec); //先用base64解密 byte[] encDataByte = cipher.doFinal(new BASE64Decoder().decodeBuffer(encData)); String decData = new String(encDataByte,StandardCharsets.UTF_8); return decData; }
使用CBC模式,需要填充一个向量,这里我直接用key来代替。
public static void main(String[] args) throws Exception { /* * 此处使用AES-128-CBC加密模式。 */ String key = "很随便的密钥"; // 需要加密的字串 String data = "即将加密的数据"; // 加密 String encData = encrypt(data, key); System.out.println("加密后的字串是:" + encData); // 解密 String decData = decrypt(encData, key); System.out.println("解密后的字串是:" + decData); } // 加密 public static String encrypt(String data, String key) throws Exception { //创建AES的Key生产者 KeyGenerator kgen = KeyGenerator.getInstance("AES"); // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥 kgen.init(128, new SecureRandom(key.getBytes())); //SecureRandom是生成安全随机数序列 SecretKey secretKey = kgen.generateKey(); byte[] rKey = secretKey.getEncoded(); // 转换为AES专用密钥 SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES"); // 创建密码器 //"算法/模式/补码方式" Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); //使用CBC模式,需要一个向量iv,可增加加密算法的强度 IvParameterSpec ips = new IvParameterSpec(rKey); // 初始化为加密模式的密码器 cipher.init(Cipher.ENCRYPT_MODE, skeySpec,ips); byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); //此处使用BASE64做转码功能,同时能起到2次加密的作用。 return new BASE64Encoder().encode(encrypted); } // 解密 public static String decrypt(String encData, String key) throws Exception { //创建AES的Key生产者 KeyGenerator kgen = KeyGenerator.getInstance("AES"); // 利用"很随便的密钥"作为随机数初始化生成一个128字节16位的密钥 kgen.init(128, new SecureRandom(key.getBytes())); //SecureRandom是生成安全随机数序列 SecretKey secretKey = kgen.generateKey(); byte[] rKey = secretKey.getEncoded(); SecretKeySpec skeySpec = new SecretKeySpec(rKey, "AES"); // 创建密码器 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//使用CBC模式,需要一个向量iv,可增加加密算法的强度 IvParameterSpec ips = new IvParameterSpec(rKey); // 初始化为解密模式的密码器 cipher.init(Cipher.DECRYPT_MODE, skeySpec,ips); //先用base64解密 byte[] encDataByte = cipher.doFinal(new BASE64Decoder().decodeBuffer(encData)); String decData = new String(encDataByte,StandardCharsets.UTF_8); return decData; }
RSA:
private static final String DATA = "要加密的数据"; private static String rsaPublicKey = null; private static String rsaPrivateKey = null; public static void main(String[] args) throws Exception { //构建密钥对 createEnck(); //私钥加密 String result = encByPrivateKey(rsaPrivateKey); //公钥解密 decByPublicKey(rsaPublicKey,result); } //构建密钥对,保存公私钥 private static void createEnck() throws Exception { KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("RSA"); senderKeyPairGenerator.initialize(512); KeyPair keyPair = senderKeyPairGenerator.generateKeyPair(); //生成公钥 RSAPublicKey rsaPublicKey1 = (RSAPublicKey) keyPair.getPublic(); //生成私钥 RSAPrivateKey rsaPrivateKey1 = (RSAPrivateKey) keyPair.getPrivate(); //这里也可以不用base64加密,看自己的需求 rsaPublicKey = Base64.encodeBase64String(rsaPublicKey1.getEncoded()); rsaPrivateKey = Base64.encodeBase64String(rsaPrivateKey1.getEncoded()); System.out.println("rsaPublicKey = "+rsaPublicKey); System.out.println("rsaPrivateKey = "+rsaPrivateKey); } /** * 私钥加密 */ private static String encByPrivateKey(String rsaPrivateKey) throws Exception { // 在构建密钥对时,对密钥做了base64编码,这里需要先解码 PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPrivateKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); //创建Cipher对象。 Cipher cipher = Cipher.getInstance("RSA"); //初始化为加密模式的密码器 //用密钥初始化 Cipher cipher.init(Cipher.ENCRYPT_MODE, privateKey); //加密 byte[] bytes = cipher.doFinal(DATA.getBytes()); String result = Base64.encodeBase64String(bytes); System.out.println("私钥加密: " + result); return result; } /** * 公钥解密 */ private static void decByPublicKey(String rsaPublicKey,String result) throws Exception { // 这里也需要对公钥进行解码 X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPublicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, publicKey); byte[] bytes = cipher.doFinal(Base64.decodeBase64(result)); System.out.println("公钥解密: " + new String(bytes)); }
private static final String DATA = "要加密的数据"; private static String rsaPublicKey = null; private static String rsaPrivateKey = null; public static void main(String[] args) throws Exception { //构建密钥对 createEnck(); //加密 String result = encByPublicKey(rsaPublicKey); //解密 decByPrivateKey(rsaPrivateKey,result); } //构建密钥对,保存公私钥 private static void createEnck() throws Exception { KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("RSA"); senderKeyPairGenerator.initialize(512); KeyPair keyPair = senderKeyPairGenerator.generateKeyPair(); //生成公钥 RSAPublicKey rsaPublicKey1 = (RSAPublicKey) keyPair.getPublic(); //生成私钥 RSAPrivateKey rsaPrivateKey1 = (RSAPrivateKey) keyPair.getPrivate(); rsaPublicKey = Base64.encodeBase64String(rsaPublicKey1.getEncoded()); rsaPrivateKey = Base64.encodeBase64String(rsaPrivateKey1.getEncoded()); System.out.println("rsaPublicKey = "+rsaPublicKey); System.out.println("rsaPrivateKey = "+rsaPrivateKey); } /** * 公钥加密 */ private static String encByPublicKey(String rsaPublicKey) throws Exception { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPublicKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] bytes = cipher.doFinal(DATA.getBytes()); String result = Base64.encodeBase64String(bytes); System.out.println("公钥加密: " + result); return result; } /** * 私钥解密 */ private static void decByPrivateKey(String rsaPrivateKey,String result) throws Exception { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec((new BASE64Decoder()).decodeBuffer(rsaPrivateKey)); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec); Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] bytes = cipher.doFinal(Base64.decodeBase64(result)); System.out.println("私钥解密解密:" + new String(bytes)); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。