当前位置:   article > 正文

常见加密算法附JAVA代码案例_加密算法代码

加密算法代码

1、对称加密算法(AES、DES、3DES)

对称加密算法是指加密和解密采用相同的密钥,是可逆的(即可解密)。

AES加密算法是密码学中的高级加密标准,采用的是对称分组密码体制,密钥长度的最少支持为128。AES加密算法是美国联邦政府采用的区块加密标准,这个标准用来替代原先的DES,已经被多方分析且广为全世界使用。

AES数学原理详解:AES加密 - block2016 - 博客园

优点:加密速度快

缺点:密钥的传递和保存是一个问题,参与加密和解密的双方使用的密钥是一样的,这样密钥就很容易泄露。

2、非对称加密算法(RSA、DSA、ECC)也叫公钥加密

非对称加密算法是指加密和解密采用不同的密钥(公钥和私钥),因此非对称加密也叫公钥加密,是可逆的(即可解密)。公钥密码体制根据其所依据的难题一般分为三类:大素数分解问题类、离散对数问题类、椭圆曲线类。

RSA加密算法是基于一个十分简单的数论事实:将两个大素数(也就是质数:质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数,例如:17、19、23、29、31、37、41等)相乘十分容易,但是想要对其乘积进行因式分解极其困难,因此可以将乘积公开作为加密密钥。虽然RSA的安全性一直未能得到理论上的证明,但它经历了各种攻击至今未被完全攻破。 

RSA公私钥生成流程

  1. 随机找两个素数P和Q,P与Q越大,越安全。(例如:61和53)

  2. 计算p和q的乘积n。(n=61×53=3233,n的长度就是密钥长度。3233写成二进制是110010100001,一共有12位,所以这个密钥就是12位。)

  3. 计算 n 的欧拉函数φ(n)。(根据公式φ(n)=(p-1)(q-1)算出φ(3233)等于60×52,即3120)

  4. 随机选择一个整数e,条件是1<e<φ(n),且e与φ(n) 互质。(条件是1<e<φ(n),且e与φ(n) 互质。1到3120之间,随机选择了17。)

  5. 有一个整数d,可以使得ed 除以φ(n) 的余数为 1。(ed ≡ 1 (mod φ(n)),即17*2753 mode 3120=1)

  6. 将n和e封装成公钥,n和d封装成私钥。(n=3233,e=17,d=2753,所以公钥就是:3233,17,私钥就是:3233, 2753。)

RSA加密

首先对明文进行比特串分组,使得每个分组对应的十进制数小于n,然后依次对每个分组m做一次加密,所有分组的密文构成的序列就是原始消息的加密结果,即m满足0<=m<n,则加密算法为:c=m^e mod n; c为密文,且0<=c<n。

欧拉函数

一.什么是欧拉函数
欧拉函数就是指:对于一个正整数n,小于或等于n的正整数中与n互质的正整数个数(包括1)的个数,记作 φ ( n )

所以其通式为: φ ( n ) = n * (1 - 1/p1) * (1 - 1/p2) * …… * (1 - 1/pn),其中p1,p2……pn为n的所有质因数,例如:φ ( 10 ) 的质因数为2,5,所有φ ( 10 ) = 10 * (1 - 1/2) * (1 - 1/5) = 4(1,3,7,9这四个数)
同时φ ( 1 ) = 1;

二.欧拉函数的一些性质
若n为质数,则φ ( n ) = n - 1;
若m与n互质,则φ ( n*m ) = φ ( n ) * φ ( m );
若正整数n与a互质,那么就有
若n为奇数时,φ ( 2n ) = φ ( n );
若n = pk且p是质数,那么φ ( n ) = (p - 1) * pk-1 = pk - pk-1

优点:512位(或是1024位)秘钥,计算量极大,难破解。加密和解密的密钥不一致,公钥是可以公开的,只需保证私钥不被泄露即可,这样就密钥的传递变的简单很多,从而降低了被破解的几率。

缺点:加密速度慢

RSA加密算法既可以用来做数据加密,也可以用来数字签名。

数据加密过程:甲方用乙方的公钥加密,乙方用自己的私钥解密(甲方为发送者,乙方为接受者,乙方事先提供自己的公钥给甲方,简称:公钥加密,私钥解密

数字签名过程:甲方用甲方的私钥加密,乙方用甲方的公钥解密(甲方为发送者,乙方为接受者,乙方解密成功说明就是甲方加的密,甲方就不可以抵赖,乙方解密需要甲方提供的公钥,简称:私钥签名,公钥验签

详细数学原理见 【来龙去脉系列】RSA算法原理

ECC加密算法是基于椭圆曲线上离散对数计算问题(ECDLP)的ECC算法。ECC算法的数学理论非常深奥和复杂,在工程应用中比较难于实现,但它的单位安全强度相对较高。

用国际上公认的对于ECC算法最有效的攻击方法--Pollard rho方法去破译和攻击ECC算法,它的破译或求解难度基本上是指数级的。正是由于RSA算法ECC算法这一明显不同,使得ECC算法的单位安全强度高于RSA算法,也就是说,要达到同样的安全强度,ECC算法所需的密钥长度远比RSA算法低。有研究表示160位的椭圆密钥与1024位的RSA密钥安全性相同。在私钥的加密解密速度上,ECC算法比RSA、DSA速度更快。存储空间占用更小。

3、线性散列算法(MD5、SHA1、HMAC)

MD5全称是Message-Digest Algorithm 5(信息摘要算法5),单向的算法不可逆(被MD5加密的数据不能被解密)。MD5加密后的数据长度要比加密数据小的多,且长度固定,且加密后的串是唯一的,MD5散列值长度位128位。

适用场景:常用在不可还原的密码存储、信息完整性校验等。

信息完整性校验:典型的应用是对一段信息产生信息摘要,以防止被篡改。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的“抵赖”,这就是所谓的数字签名应用。

SHA-1 与 MD5 的比较

SHA-1摘要比MD5摘要长32 位,散列值长度160位,所以SHA-1对强行攻击有更大的强度,比MD5更安全。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2^128数量级的操作,而对SHA-1则是2^160数量级的操作。

在相同的硬件上,SHA-1 的运行速度比 MD5 慢。

4、混合加密

由于以上加密算法都有各自的缺点(RSA加密速度慢、AES密钥存储问题、MD5加密不可逆),因此实际应用时常将几种加密算法混合使用。

例如:RSA+DES,RSA+AES:

采用DES对数据进行加密,而RSA对DES的密钥加密,这样集成了两种加密算法的优点,既保证了数据加密的速度,又实现了安全方便的密钥管理。

那么,采用多少位的密钥合适呢?一般来讲密钥长度越长,安全性越高,但是加密速度越慢。所以密钥长度也要合理的选择,一般RSA建议采用1024位的数字,AES建议采用128位即可。

这里写图片描述

混合加密代码案例:RSA+DES

  1. /**
  2. * RSA加密
  3. * @param data 待加密数据
  4. * @param publicKey 公钥
  5. */
  6. public static String rsaEncrypt(String data, PublicKey publicKey) throws Exception {
  7. Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
  8. cipher.init(Cipher.ENCRYPT_MODE, publicKey);
  9. int inputLen = data.getBytes().length;
  10. ByteArrayOutputStream out = new ByteArrayOutputStream();
  11. int offset = 0;
  12. byte[] cache;
  13. int i = 0;
  14. // 对数据分段加密
  15. while (inputLen - offset > 0) {
  16. if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
  17. cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
  18. } else {
  19. cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
  20. }
  21. out.write(cache, 0, cache.length);
  22. i++;
  23. offset = i * MAX_ENCRYPT_BLOCK;
  24. }
  25. byte[] encryptedData = out.toByteArray();
  26. out.close();
  27. return Base64.encodeBase64String(encryptedData);
  28. }
  29. /**
  30. * RSA解密
  31. * @param secretData 待解密数据
  32. * @param privateKey 私钥
  33. */
  34. public static String rsaDecrypt(String secretData, PrivateKey privateKey) throws Exception {
  35. Cipher cipher = Cipher.getInstance(ALGORITHM_NAME);
  36. cipher.init(Cipher.DECRYPT_MODE, privateKey);
  37. byte[] dataBytes = Base64.decodeBase64(secretData);
  38. int inputLen = dataBytes.length;
  39. ByteArrayOutputStream out = new ByteArrayOutputStream();
  40. int offset = 0;
  41. byte[] cache;
  42. int i = 0;
  43. // 对数据分段解密
  44. while (inputLen - offset > 0) {
  45. if (inputLen - offset > MAX_DECRYPT_BLOCK) {
  46. cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
  47. } else {
  48. cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
  49. }
  50. out.write(cache, 0, cache.length);
  51. i++;
  52. offset = i * MAX_DECRYPT_BLOCK;
  53. }
  54. byte[] decryptedData = out.toByteArray();
  55. out.close();
  56. return new String(decryptedData, StandardCharsets.UTF_8);// 解密后的内容
  57. }
  58. /**
  59. * DES加密
  60. * @param data 待加密数据
  61. * @param desKey 长度要是8的倍数且不能小于8位
  62. * @return String
  63. */
  64. public static String desEncrypt(String data, String desKey) {
  65. try{
  66. if (desKey== null || desKey.length() < 8) {
  67. throw new RuntimeException("加密失败,desKey不能小于8位");
  68. }
  69. SecureRandom random = new SecureRandom();
  70. DESKeySpec desKeySpec = new DESKeySpec(desKey.getBytes());
  71. //创建一个密匙工厂,然后用它把DESKeySpec转换成
  72. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  73. SecretKey securekey = keyFactory.generateSecret(desKeySpec);
  74. //Cipher对象实际完成加密操作
  75. Cipher cipher = Cipher.getInstance("DES");
  76. //用密匙初始化Cipher对象
  77. cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
  78. //现在,获取数据并加密
  79. //正式执行加密操作
  80. byte[] encryptedData = cipher.doFinal(data.getBytes());
  81. return Base64.encodeBase64String(encryptedData);
  82. }catch(Throwable e){
  83. e.printStackTrace();
  84. }
  85. return null;
  86. }
  87. /**
  88. * DES解密
  89. * @param secretData base64编码得解密数据
  90. * @param desKey
  91. * @return byte[]
  92. * @throws Exception
  93. */
  94. public static String desDecrypt(String secretData, String desKey) throws Exception {
  95. // DES算法要求有一个可信任的随机数源
  96. SecureRandom random = new SecureRandom();
  97. // 创建一个DESKeySpec对象
  98. DESKeySpec desKeySpec = new DESKeySpec(desKey.getBytes(StandardCharsets.UTF_8));
  99. // 创建一个密匙工厂
  100. SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
  101. // 将DESKeySpec对象转换成SecretKey对象
  102. SecretKey securekey = keyFactory.generateSecret(desKeySpec);
  103. // Cipher对象实际完成解密操作
  104. Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
  105. // 用密匙初始化Cipher对象
  106. cipher.init(Cipher.DECRYPT_MODE, securekey, random);
  107. // 真正开始解密操作
  108. byte[] decryptedData = cipher.doFinal(Base64.decodeBase64(secretData));
  109. return new String(decryptedData,StandardCharsets.UTF_8);
  110. }
  111. /**
  112. * RSA和DES混合加密
  113. * @param data 待加密数据
  114. * @param publicKey RSA公钥
  115. * @return
  116. */
  117. public static Map<String,Object> encrypt(String data, String publicKey) throws Exception {
  118. String desKey = getRandomKey();//随机生成密钥
  119. String encryptData = desEncrypt(data,desKey);//用des加密原数据
  120. String encryptDESKey = rsaEncrypt(desKey,getPublicKey(publicKey));//用RSA加密deskey
  121. Map dataMap = new HashMap();
  122. dataMap.put("secretData",encryptData);
  123. dataMap.put("desKey",encryptDESKey);
  124. log.info("待加密随机DES秘钥->desKey:"+desKey);
  125. return dataMap;
  126. }
  127. /**
  128. * RSA和DES混合解密
  129. * @param secretData 待解密数据
  130. * @param desKey 通过Rsa加密的DESKey
  131. * @param privateKey RSA私钥
  132. * @return
  133. */
  134. public static String decrypt(String secretData, String desKey, String privateKey) throws Exception {
  135. //使用Rsa解密DESKey,用到私钥privateKey
  136. String decryptDESKey = rsaDecrypt(desKey,getPrivateKey(privateKey));
  137. log.info("已解密随机DES秘钥->desKey:"+decryptDESKey);
  138. //再使用des解密数据,用到已解密出的DESKey
  139. return desDecrypt(secretData,decryptDESKey);
  140. }
  141. public static void main(String[] args) throws Exception {
  142. String str = "你好啊,JAVA!";
  143. log.info("待加密数据:"+str.trim());
  144. Map keyMap = getKeyPairMap();//RSA生成秘钥对
  145. String publicKey = keyMap.get("publicKey").toString();//Rsa公钥
  146. String privateKey = keyMap.get("privateKey").toString();//Rsa私钥
  147. log.info("RSA秘钥对->publicKey:"+publicKey);
  148. log.info("RSA秘钥对->privateKey:"+privateKey);
  149. Map<String,Object> dataMap = encrypt(str.trim(), publicKey);
  150. log.info("已加密数据:" + JSONObject.toJSONString(dataMap));
  151. String desKey = dataMap.get("desKey").toString();//已加密的desKey
  152. log.info("已加密的DES秘钥->desKey:"+desKey);
  153. String secretData = dataMap.get("secretData").toString();//待解密数据
  154. String data = decrypt(secretData, desKey, privateKey);
  155. log.info("已解密数据:" + data.trim());
  156. }

运行结果如下:

5、Base64

严格意义讲,Base64并不能算是一种加密算法,而是一种编码格式,是网络上最常见的用于传输8bid字节代码的编码方式之一。

Base64编码可用于在HTTP环境下传递较长的标识信息,Base编码不仅不仅比较简单,同时也据有不可读性

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/867163
推荐阅读
相关标签
  

闽ICP备14008679号