当前位置:   article > 正文

「第十一章」加密算法与随机数_加密 客户端随机数

加密 客户端随机数
  1. 「第三篇」服务器端应用安全
  2. 批注
  3. [……] 表示他人、自己、网络批注
  4. 参考资料来源于
  5. * 书中批注
  6. * CSDN
  7. * GitHub
  8. * Google
  9. * 维基百科
  10. * YouTube
  11. * MDN Web Docs
  12. 由于编写过程中无法记录所有的URL
  13. 所以如需原文,请自行查询
  14. {……} 重点内容
  15. *……* 表示先前提到的内容,不赘述
  16. 「第三篇」服务器端应用安全
  17. 0.6本书结构」
  18. 就常见的服务器端应用安全问题进行了阐述
  19. 这些问题往往能引起非常严重的后果,在网站的安全建设之初需要优先解决这些问题,避免留下任何隐患
  20. 「第十一章」加密算法与随机数
  21. [
  22. 使用加密算法的目的
  23. * 数据保密性,防止用户数据被窃取或泄露
  24. * 数据完整性,防止用户传输的数据被篡改
  25. * 通信双方身份确认,确保数据来源合法
  26. 常见的加密算法
  27. * 单向散列加密算法
  28. * md5
  29. * sha1
  30. * sha256
  31. * 对称加密算法
  32. * des
  33. * 3des
  34. * aes
  35. * 非对称加密算法
  36. * rsa
  37. * ecc
  38. 加密算法对比
  39. * 单向散列加密算法
  40. * md5
  41. 运行速度:快
  42. 安全性:中
  43. * sha1
  44. 运行速度:慢
  45. 安全性:高
  46. * sha256
  47. 运行速度:极慢
  48. 安全性:极高
  49. * 对称加密算法
  50. * des
  51. 密钥:56
  52. 运行速度:较快
  53. 安全性:低
  54. 资源消耗:中
  55. * 3des
  56. 密钥:112位或168
  57. 运行速度:慢
  58. 安全性:中
  59. 资源消耗:高
  60. * aes
  61. 密钥:128位或192位或256
  62. 运行速度:快
  63. 安全性:高
  64. 资源消耗:低
  65. * 非对称加密算法
  66. * rsa
  67. 成熟度:高
  68. 安全性:高
  69. 运算速度:中
  70. 资源消耗:中
  71. * ecc
  72. 成熟度:高
  73. 安全性:高
  74. 运算速度:慢
  75. 资源消耗:高
  76. 单向散列加密
  77. 单向散列加密算法常用于提取数据,验证数据的完整性
  78. 发送者将明文通过单向加密算法加密生成定长的密文串,然后将明文和密文串传递给接收方
  79. 接收方在收到报文后,将解明文使用相同的单向加密算法进行加密,得出加密后的密文串
  80. 随后与发送者发送过来的密文串进行对比,若发送前和发送后的密文串相一致,则说明传输过程中数据没有损坏,若不一致,说明传输过程中数据丢失了
  81. 其次也用于密码加密传递存储
  82. 单向加密算法只能用于对数据的加密,无法被解密,其特点为定长输出、雪崩效应
  83. md5加密
  84. MD5加密算法用的是哈希函数,一般应用于对信息产生信息摘要,防止信息被篡改
  85. 最常见的使用是对密码加密、生成数字签名
  86. 从严格意义上来说,MD5是摘要算法,并非加密算法
  87. MD5生成密文时,无论要加密的字符串有多长,它都会输出长度为128bits的一个密文串,通常16进制时为32个字符
  88. -----------------------------------------------------------------
  89. public static final byte[] computeMD5(byte[] content)
  90. {
  91. try
  92. {
  93. MessageDigest md5 = MessageDigest.getInstance("MD5");
  94. return md5.digest(content);
  95. }
  96. catch (NoSuchAlgorithmException e)
  97. {
  98. throw new RuntimeException(e);
  99. }
  100. }
  101. -----------------------------------------------------------------
  102. sha1加密
  103. SHA1加密算法,与MD5一样,也是目前较流行的摘要算法
  104. 但SHA1比MD5的安全性更高
  105. 对长度小于2^64位的消息,SHA1会产生一个160位的消息摘要
  106. 基于MD5、SHA1的信息摘要特性以及不可逆,可以被应用在检查文件完整性,数字签名等场景
  107. -----------------------------------------------------------------
  108. public static byte[] computeSHA1(byte[] content)
  109. {
  110. try
  111. {
  112. MessageDigest sha1 = MessageDigest.getInstance("SHA1");
  113. return sha1.digest(content);
  114. }
  115. catch (NoSuchAlgorithmException e)
  116. {
  117. throw new RuntimeException(e);
  118. }
  119. }
  120. -----------------------------------------------------------------
  121. sha256加密
  122. SHA256是SHA2算法中的一种
  123. 如SHA2加密算法中有
  124. * SHA244
  125. * SHA256
  126. * SHA512
  127. SHA2属于SHA1的升级,SHA1160位的哈希值,而SHA2是组合值,有不同的位数,其中最受欢迎的是256位(SHA256算法)
  128. SSL行业选择SHA作为数字签名的散列算法,从20112015,一直以SHA-1位主导算法
  129. 但随着互联网技术的提升,SHA-1的缺点越来越突显
  130. 从去年起,SHA-2成为了新的标准,所以现在签发的SSL证书,必须使用该算法签名
  131. -------------------------------------------------------------
  132. public static byte[] getSHA256(String str)
  133. {
  134. MessageDigest messageDigest;
  135. String encodestr = "";
  136. try
  137. {
  138. messageDigest = MessageDigest.getInstance("SHA-256");
  139. messageDigest.update(str.getBytes("UTF-8"));
  140. return messageDigest.digest());
  141. }
  142. catch (NoSuchAlgorithmException e)
  143. {
  144. e.printStackTrace();
  145. }
  146. catch (UnsupportedEncodingException e)
  147. {
  148. e.printStackTrace();
  149. }
  150. }
  151. -------------------------------------------------------------
  152. 对称加密
  153. 对称加密算法采用单密钥加密,在数据传输过程中,发送方将原始数据分割成固定大小的块,经过密钥和加密算法逐个加密后,发送给接收方,接收方收到加密后的报文后,结合密钥和解密算法解密组合后得出原始数据
  154. 由于加解密算法是公开的,因此在这过程中,密钥的安全传递就成为了至关重要的事了
  155. 而密钥通常来说是通过双方协商,以物理的方式传递给对方,或者利用第三方平台传递给对方,一旦这过程出现了密钥泄露,不怀好意的人就能结合相应的算法拦截解密出其加密传输的内容
  156. AES、DES、3DES都是对称的块加密算法,加解密的过程是可逆的
  157. des算法
  158. DES算法为密码体制中的对称密码体制,又被称为美国数据加密标准,是1972年美国IBM公司研制的对称密码体制加密算法
  159. 明文按64位进行分组,密钥长64位,密钥事实上是56位参与DES运算(第816243240485664位是校验位,使得每个密钥都有奇数个1)分组后的明文组和56位的密钥按位替代或交换的方法形成密文组的加密方法
  160. DES加密算法是对密钥进行保密,公开加密和解密算
  161. 只有知道发送方相同密钥的人才能解读获取的密文数据
  162. 想破译DES加密算法,就要搜索密钥的编码
  163. 对于56位长度的密钥来说,用穷举法,其运算次数为2^56
  164. 3des算法
  165. 3DES又称Triple DES,是DES加密算法的一种模式,它使用2条不同的56位的密钥对数据进行三次加密
  166. DES使用56位密钥和密码块的方法,而在密码块的方法中,文本被分成64位大小的文本块然后再进行加密
  167. 比起最初的DES,3DES更为安全
  168. ---------------------------------------------------------------------
  169. public class Des3
  170. {
  171. private static final String Algorithm = "DESede";
  172. /**
  173. * 加密
  174. * @param keybyte
  175. * @param src
  176. * @return
  177. */
  178. public static byte[] encryptMode(byte[] keybyte, byte[] src)
  179. {
  180. try
  181. {
  182. // 生成密钥
  183. SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
  184. // 加密
  185. Cipher c1 = Cipher.getInstance(Algorithm);
  186. c1.init(Cipher.ENCRYPT_MODE, deskey);
  187. return c1.doFinal(src);
  188. }
  189. catch (java.security.NoSuchAlgorithmException e1)
  190. {
  191. e1.printStackTrace();
  192. }
  193. catch (javax.crypto.NoSuchPaddingException e2)
  194. {
  195. e2.printStackTrace();
  196. }
  197. catch (java.lang.Exception e3)
  198. {
  199. e3.printStackTrace();
  200. }
  201. return null;
  202. }
  203. /**
  204. * 解密
  205. * @param keybyte 为加密密钥,长度为24字节
  206. * @param src 为加密后的缓冲区
  207. * @return
  208. */
  209. public static byte[] decryptMode(byte[] keybyte, byte[] src)
  210. {
  211. try
  212. {
  213. // 生成密钥
  214. SecretKey deskey = new SecretKeySpec(keybyte, Algorithm);
  215. // 解密
  216. Cipher c1 = Cipher.getInstance(Algorithm);
  217. c1.init(Cipher.DECRYPT_MODE, deskey);
  218. return c1.doFinal(src);
  219. }
  220. catch (Exception e)
  221. {
  222. e.printStackTrace();
  223. }
  224. return null;
  225. }
  226. // 转换成十六进制字符串
  227. public static String byte2hex(byte[] b)
  228. {
  229. String hs = "";
  230. String stmp = "";
  231. for (int n = 0; n < b.length; n++)
  232. {
  233. stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
  234. if (stmp.length() == 1)
  235. {
  236. hs = hs + "0" + stmp;
  237. }
  238. else
  239. {
  240. hs = hs + stmp;
  241. }
  242. if (n < b.length - 1)
  243. {
  244. hs = hs + ":";
  245. }
  246. }
  247. return hs.toUpperCase();
  248. }
  249. }
  250. ---------------------------------------------------------------------
  251. aes算法
  252. AES算法是密码学中的高级加密标准,同时也是美国联邦政府采用的区块加密标准
  253. 这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用
  254. 算法采用对称分组密码体制,密钥长度的最少支持为128位、192位、256位,分组长度128位,算法应易于各种硬件和软件实现
  255. AES本身就是为了取代DES的,AES具有更好的安全性、效率和灵活性
  256. --------------------------------------------------------------------------------
  257. public class AESUtils
  258. {
  259. /**
  260. * 加密
  261. *
  262. * @param content
  263. * @param strKey
  264. * @return
  265. * @throws Exception
  266. */
  267. public static byte[] encrypt(String content, String strKey) throws Exception
  268. {
  269. SecretKeySpec skeySpec = getKey(strKey);
  270. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  271. IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());
  272. cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
  273. return cipher.doFinal(content.getBytes());
  274. }
  275. /**
  276. * 解密
  277. *
  278. * @param strKey
  279. * @param content
  280. * @return
  281. * @throws Exception
  282. */
  283. public static String decrypt(byte[] content, String strKey) throws Exception
  284. {
  285. SecretKeySpec skeySpec = getKey(strKey);
  286. Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
  287. IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());
  288. cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
  289. byte[] original = cipher.doFinal(content);
  290. String originalString = new String(original);
  291. return originalString;
  292. }
  293. private static SecretKeySpec getKey(String strKey) throws Exception
  294. {
  295. byte[] arrBTmp = strKey.getBytes();
  296. byte[] arrB = new byte[16];
  297. for (int i = 0; i < arrBTmp.length && i < arrB.length; i++)
  298. {
  299. arrB[i] = arrBTmp[i];
  300. }
  301. SecretKeySpec skeySpec = new SecretKeySpec(arrB, "AES");
  302. return skeySpec;
  303. }
  304. }
  305. --------------------------------------------------------------------------------
  306. 非对称加密算法
  307. 非对称加密算法采用公钥(publickey)和私钥(privatekey)两种不同的密钥来进行加解密
  308. 公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密,反之亦然
  309. 因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法
  310. 非对称加密算法实现机密信息交换的基本过程是,甲方生成一对密钥并将公钥公开,需要向甲方发送信息的其他角色(乙方)使用该密钥(甲方的公钥)对机密信息进行加密后再发送给甲方,甲方再用自己私钥对加密后的信息进行解密
  311. 甲方想要回复乙方时正好相反,使用乙方的公钥对数据进行加密,同理,乙方使用自己的私钥来进行解密
  312. rsa算法
  313. RSA是目前最有影响力的公钥加密算法,也是被普遍认为是目前最优秀的公钥方案之一
  314. RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作
  315. RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,截止2017年被普遍认为是最优秀的公钥方案之一
  316. 也已被ISO推荐为公钥数据加密标准
  317. ---------------------------------------------------------------------------------------------
  318. public class RSAUtils
  319. {
  320. public static final String KEY_ALGORITHM = "RSA";
  321. private static final String PUBLIC_KEY = "RSAPublicKey";
  322. private static final String PRIVATE_KEY = "RSAPrivateKey";
  323. /**
  324. * 私钥解密
  325. *
  326. * @param data 已加密数据
  327. * @param privateKey 私钥(BASE64编码)
  328. * @return
  329. * @throws Exception
  330. */
  331. public static String decryptByPrivateKey(String data, String privateKey) throws Exception
  332. {
  333. byte[] keyBytes = Base64.decodeBase64(privateKey);
  334. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  335. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  336. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  337. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  338. cipher.init(Cipher.DECRYPT_MODE, privateK);
  339. byte[] buff = cipher.doFinal(Base64.decodeBase64(data));
  340. return new String(buff);
  341. }
  342. /**
  343. * 公钥解密
  344. *
  345. * @param data 已加密数据
  346. * @param publicKey 公钥(BASE64编码)
  347. * @return
  348. * @throws Exception
  349. */
  350. public static String decryptByPublicKey(String data, String publicKey) throws Exception
  351. {
  352. byte[] keyBytes = Base64.decodeBase64(publicKey);
  353. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  354. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  355. Key publicK = keyFactory.generatePublic(x509KeySpec);
  356. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  357. cipher.init(Cipher.DECRYPT_MODE, publicK);
  358. // 执行解密操作
  359. byte[] buff = cipher.doFinal(Base64.decodeBase64(data));
  360. return new String(buff);
  361. }
  362. /**
  363. * 公钥加密
  364. *
  365. * @param data 源数据
  366. * @param publicKey 公钥(BASE64编码)
  367. * @return
  368. * @throws Exception
  369. */
  370. public static String encryptByPublicKey(String data, String publicKey) throws Exception
  371. {
  372. byte[] keyBytes = Base64.decodeBase64(publicKey);
  373. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  374. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  375. Key publicK = keyFactory.generatePublic(x509KeySpec);
  376. // 对数据加密
  377. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  378. cipher.init(Cipher.ENCRYPT_MODE, publicK);
  379. byte[] buff = cipher.doFinal(data.getBytes());
  380. return Base64.encodeBase64String(buff);
  381. }
  382. /**
  383. * 私钥加密
  384. *
  385. * @param data 源数据
  386. * @param privateKey 私钥(BASE64编码)
  387. * @return
  388. * @throws Exception
  389. */
  390. public static String encryptByPrivateKey(String data, String privateKey) throws Exception
  391. {
  392. byte[] keyBytes = Base64.decodeBase64(privateKey);
  393. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  394. KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
  395. Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
  396. Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
  397. cipher.init(Cipher.ENCRYPT_MODE, privateK);
  398. byte[] buff = cipher.doFinal(data.getBytes());
  399. // 执行加密操作。加密后的结果通常都会用Base64编码进行传输
  400. return Base64.encodeBase64String(buff);
  401. }
  402. /**
  403. * 获取私钥
  404. *
  405. * @param keyMap 密钥对
  406. * @return
  407. * @throws Exception
  408. */
  409. public static String getPrivateKey(Map<String, Object> keyMap) throws Exception
  410. {
  411. Key key = (Key) keyMap.get(PRIVATE_KEY);
  412. return Base64.encodeBase64String(key.getEncoded());
  413. }
  414. /**
  415. * 获取公钥
  416. *
  417. * @param keyMap 密钥对
  418. * @return
  419. * @throws Exception
  420. */
  421. public static String getPublicKey(Map<String, Object> keyMap) throws Exception
  422. {
  423. Key key = (Key) keyMap.get(PUBLIC_KEY);
  424. return Base64.encodeBase64String(key.getEncoded());
  425. }
  426. /**
  427. * 生成密钥对(公钥和私钥)
  428. *
  429. * @return
  430. * @throws Exception
  431. */
  432. public static Map<String, Object> initKey() throws Exception
  433. {
  434. KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
  435. keyPairGen.initialize(1024);
  436. KeyPair keyPair = keyPairGen.generateKeyPair();
  437. RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
  438. RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
  439. Map<String, Object> keyMap = new HashMap<String, Object>(2);
  440. keyMap.put(PUBLIC_KEY, publicKey);
  441. keyMap.put(PRIVATE_KEY, privateKey);
  442. return keyMap;
  443. }
  444. }
  445. ---------------------------------------------------------------------------------------------
  446. ecc算法
  447. ECC(椭圆加密算法)是一种公钥加密体制,主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全
  448. 不过一个缺点是加密和解密操作的实现比其他机制时间长
  449. 它相比RSA算法,对CPU消耗严重
  450. ---------------------------------------------------------------------------------------------------
  451. public abstract class ECCCoder extends Coder
  452. {
  453. public static final String ALGORITHM = "EC";
  454. private static final String PUBLIC_KEY = "ECCPublicKey";
  455. private static final String PRIVATE_KEY = "ECCPrivateKey";
  456. /**
  457. * 用私钥解密
  458. * @param data
  459. * @param key
  460. * @return
  461. * @throws Exception
  462. */
  463. public static byte[] decrypt(byte[] data, String key) throws Exception
  464. {
  465. // 对密钥解密
  466. byte[] keyBytes = decryptBASE64(key);
  467. // 取得私钥
  468. PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
  469. KeyFactory keyFactory = ECKeyFactory.INSTANCE;
  470. ECPrivateKey priKey = (ECPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
  471. ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(priKey.getS(),priKey.getParams());
  472. // 对数据解密
  473. Cipher cipher = new NullCipher();
  474. cipher.init(Cipher.DECRYPT_MODE, priKey, ecPrivateKeySpec.getParams());
  475. return cipher.doFinal(data);
  476. }
  477. /**
  478. * 用公钥加密
  479. * @param data
  480. * @param privateKey
  481. * @return
  482. * @throws Exception
  483. */
  484. public static byte[] encrypt(byte[] data, String privateKey) throws Exception
  485. {
  486. // 对公钥解密
  487. byte[] keyBytes = decryptBASE64(privateKey);
  488. // 取得公钥
  489. X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
  490. KeyFactory keyFactory = ECKeyFactory.INSTANCE;
  491. ECPublicKey pubKey = (ECPublicKey) keyFactory.generatePublic(x509KeySpec);
  492. ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(pubKey.getW(), pubKey.getParams());
  493. Cipher cipher = new NullCipher();
  494. cipher.init(Cipher.ENCRYPT_MODE, pubKey, ecPublicKeySpec.getParams());
  495. return cipher.doFinal(data);
  496. }
  497. /**
  498. * 取得私钥
  499. * @param keyMap
  500. * @return
  501. * @throws Exception
  502. */
  503. public static String getPrivateKey(Map<String, Object> keyMap) throws Exception
  504. {
  505. Key key = (Key) keyMap.get(PRIVATE_KEY);
  506. return encryptBASE64(key.getEncoded());
  507. }
  508. /**
  509. * 取得公钥
  510. * @param keyMap
  511. * @return
  512. * @throws Exception
  513. */
  514. public static String getPublicKey(Map<String, Object> keyMap) throws Exception
  515. {
  516. Key key = (Key) keyMap.get(PUBLIC_KEY);
  517. return encryptBASE64(key.getEncoded());
  518. }
  519. }
  520. ---------------------------------------------------------------------------------------------------
  521. ]
  522. [
  523. md5详解
  524. md5的用处
  525. 无论是密码记录用户验证还是文件完整性存储,笼统的说就是验证数据是否匹配
  526. 数据库中使用明文记录密码明显是不可行的,但是使用MD5就不同了,MD5算法的高明之处就是不可逆,因为在算法中采取了抽样、分组等等算法,他不会将数据的所有内容加入运算,而是根据规则选择指定内容运算,所以,同样的字符串或者内容进行MD5运算的时候,得到的结果也是一样的,所以使用MD5记录密码,可以很有效的解决一些明文带来的问题,至于验证数据准确性就更加不用说了
  527. md5有相同
  528. MD5有相同这个已经算是被承认的,但是几率非常小
  529. MD5相同的情况叫做碰撞,现在网络中已经出现了两个相同的MD5可执行文件,你可能会问,MD5相同到底会造成什么问题
  530. 一些网盘使用的是MD5的方式来验证文件是否已经被上传过,如果上传过就直接告诉用户上传过就好了,也就不用再次上传去占用而外的空间,假设Win9现在发布了,我马上就构造一个假的包含病毒的但是MD5和官方镜像相同的安装镜像放置到A网盘,A网盘使用MD5验证数据是否相同,那么现在的问题就是,用户下载的全部都是我制作的光盘,而非微软官方的
  531. 当然,这种构造的方法仍然是非常高级的东西,不是很容易能够做到的
  532. 字符串1
  533. 4d c9 68 ff 0e e3 5c 20 95 72 d4 77 7b 72 15 87 d3 6f a7 b2 1b dc 56 b7 4a 3d c0 78 3e 7b 95 18 af bf a2 00 a8 28 4b f3 6e 8e 4b 55 b3 5f 42 75 93 d8 49 67 6d a0 d1 55 5d 83 60 fb 5f 07 fe a2
  534. 字符串2
  535. 4d c9 68 ff 0e e3 5c 20 95 72 d4 77 7b 72 15 87 d3 6f a7 b2 1b dc 56 b7 4a 3d c0 78 3e 7b 95 18 af bf a2 02 a8 28 4b f3 6e 8e 4b 55 b3 5f 42 75 93 d8 49 67 6d a0 d1 d5 5d 83 60 fb 5f 07 fe a2
  536. 两个字符串的MD5值完全相同
  537. 需要担心的问题
  538. MD5会发生碰撞已经是被发现的了,但是我们需要担心吗,我要说的是,目前为止还不用担心,首先要构造MD5碰撞是非常难的,理论上字符串越长MD5就越不可能相同,并且借助SHA-1算法的帮助,双管齐下,也就没有太大问题了,所以现在MD5还没有轮到被弃用的时候
  539. sha-1是否会碰撞
  540. SHA-1也会发生碰撞,但是几率比MD5小的多
  541. 如何解决碰撞
  542. 解决碰撞其实可以通过MD5和SHA-1结合使用来实现
  543. 我是这样做的,首先将文件A的MD5值记为B再把A的SHA-1记为C,之后用将B和C相加之后再次运算MD5值就好了,MD5值碰撞的几率已经很小,再结合SHA-1的话,基本上就不会发生碰撞的问题出现了
  544. 在新的算法普及之前,MD5还是可以继续使用的
  545. ]
  546. 11.1概述」
  547. 加密算法与伪随机数算法是开发中经常会用到的东西,但加密算法的专业性非常强,在Web开发中,如果对加密算法和伪随机数算法缺乏一定的了解,则很可能会错误地使用它们,最终导致应用出现安全问题
  548. 密码学有着悠久的历史,它满足了人们对安全的最基本需求————保密性
  549. 密码学可以说是安全领域发展的基础
  550. 在Web应用中,常常可以见到加密算法的身影,最常见的就是网站在将敏感信息保存到Cookie时使用的加密算法
  551. 加密算法的运用是否正确,与网站的安全息息相关
  552. 常见的加密算法通常分为分组加密算法与流密码加密算法,两者的实现原理不同
  553. 分组加密算法基于分组(block)进行操作,根据算法的不同,每个分组的长度可能不同
  554. 分组加密算法的代表
  555. DES
  556. 3-DES
  557. Blowfish
  558. IDEA
  559. AES
  560. ...
  561. 流密码加密算法,则每次只处理一个字节,密钥独立于消息之外,两者通过异或实现加密与解密
  562. 流密码加密算法的代表
  563. RC4
  564. ORYX
  565. SEAL
  566. ...
  567. 针对加密算法的攻击,一般根据攻击者能获得的信息,可以分为
  568. * 唯密文攻击
  569. 攻击者有一些密文,它们是使用同一加密算法和同一密钥加密的
  570. 这种攻击是最难的
  571. * 已知明文攻击
  572. 攻击者除了能得到一些密文外,还能得到这些密文对应的明文
  573. * 选择明文攻击
  574. 攻击者不仅能得到一些密文和明文,还能选择用于加密的明文
  575. * 选择密文攻击
  576. 攻击者可以选择不同的密文来解密
  577. Padding Oracle Attack就是一种选择密文攻击
  578. 密码学在整个安全领域中是非常大的一个课题
  579. 11.2Stream Cipher Attack」
  580. 流密码是常用的一种加密算法,与分组加密算法不同,流密码的加密是基于异或(XOR)操作进行的,每次都只操作一个字节
  581. 但流密码加密算法的性能非常好,因此也是非常受开发者欢迎的一种加密算法
  582. 常见的流密码加密算法
  583. RC4
  584. ORYX
  585. SEAL
  586. ...
  587. 11.2.1Reused Key Attack
  588. 在流密码的使用中,最常见的错误便是使用同一个密钥进行多次加/解密,这将使得破解流密码变得非常简单
  589. 这种攻击被称为Reused Key Attack,在这种攻击下,攻击者不需要知道密钥,即可还原出明文
  590. 假设有密钥C、明文A、明文B,那么XOR可以表示为
  591. --------------
  592. E(A) = A xor C
  593. E(B) = B xor C
  594. --------------
  595. 这种密文是公开于众的,因此很容易计算
  596. -------------
  597. E(A) xor E(B)
  598. -------------
  599. 因为两个相同的数进行XOR运算的结果是0
  600. -----------------------------------------------------------------------
  601. E(A) xor E(B) = (A xor C) xor (B xor C) = A xor B xor C xor C = A xor B
  602. -----------------------------------------------------------------------
  603. 这意味着4个数据中,只需要知道3个,就可以推导出剩下的一个
  604. 如果存在初始化向量,则相同明文每次加密的结果均不同,将增加破解的难度,即不受此攻击影响,因此当$ckey_length = 4;时,authcode()将产生随机密钥,算法的强度也就增加了
  605. 如果IV不够随机,攻击者有可能找到相同的IV,则在相同IV的情况下仍然可以实施Reused Key Attack
  606. 11.2.2Bit-flipping Attack
  607. 再次回到这个公式
  608. -----------------------
  609. E(A) xor E(B) = A xor B
  610. -----------------------
  611. 由此可以得出
  612. -----------------------
  613. A xor E(A) xor B = E(B)
  614. -----------------------
  615. 这意味着当知道A的明文、B的明文、A的密文时,可以推导出B的密文,这在实际应用中非常有用
  616. 比如一个网站应用,使用Cookie作为用户身份的认证凭证,而Cookie的值是通过XOR加密而得的
  617. 认证的过程就是服务器端解密Cookie后,检查明文是否合法
  618. 假设明文是username + role
  619. 那么当攻击者注册了一个普通用户A时,获取了A的Cookie为Cookie(A),就有可能构造出管理员的Cookie
  620. 从而获得管理员权限
  621. -------------------------------------------------------------------------------
  622. (accountA + member) xor Coolie(A) xor (admin_account + manager) = Coolie(admin)
  623. -------------------------------------------------------------------------------
  624. 在密码学中,攻击者在不知道明文的情况下,通过改变密文,使得明文按其需要的方式发生改变的攻击方式,被称为Bit-flipping Attack
  625. http://en.wikipedia.org/wili/Bit-flipping_attack
  626. 解决Bit-flipping攻击的方法是验证密文的完整性,最常见的方法是增加带有KEY的MAC(消息验证码,Message Authentication Code),通过MAC验证密文是否被篡改
  627. 通过哈希算法来实现的MAC,称为HMAC,HMAC由于其性能较好,而被广泛使用
  628. 在authcode()中,其实已经实现了HMAC,所以攻击者在不知晓加密KEY的情况下,是无法完成Bit-flipping攻击的
  629. 其中,密文的前10个字节用于验证时间是否有效,10~26个字节即为HMAC,用于验证密文是否被篡改,26个字节之后才是真正的密文
  630. 这个值与两个因素有关,一个是真正的密文:substr($result,26),一个是$keyb,而$keyb?又是由加密密钥KEY变化得到的,因此在不知晓KEY的情况下,这个HMAC的值是无法伪造出来的,因此HMAC有效地保证了密文不会被篡改
  631. 11.2.3弱随机IV问题
  632. 在authcode()函数中,它默认使用了4字节的IV(就是函数中的keyc),使得破解难度增大
  633. 但其实4字节的IV是很脆弱的,它不够随机,我们完全可以通过暴破的方式找到重复的IV
  634. 为了验证这一点,调整一下破解程序
  635. 在大约16秒后,共遍历了19295个不同的XOR KEY,找到了相同的IV,顺利破解出明文
  636. 11.3WEP破解」
  637. 流密码加密算法存在Reused Key Attack和Bit-flipping Attack等攻击方式
  638. 而在现实中,一种最著名的针对流密码的攻击可能就是WEP密钥的破解
  639. WEP是一种常用的无线加密传输协议,破解了WEP的密钥,就可以以此密钥连接无线的Access Point
  640. WEP采用RC4算法,也存在这两种攻击方式
  641. WEP在加密过程中,有两个关键因素,一个是初始化向量IV,一个是对消息的CRC-32校验,而这两者都可以通过一些方法克服
  642. IV以明文的形式发送,在WEP中采用24bit的IV,但这其实不是很大的一个值
  643. 假设一个繁忙的AP,以11Mbps的速度发送大小为1500bytes的包,则1500*8/(11*10^6)*2^24 =~18000秒,约为5个小时
  644. 因此最多5个小时,IV就将耗光,不得不开始出现重复的IV
  645. 在实际情况中,并非每个包都有1500bytes大小,因此时间会更短
  646. IV一旦开始重复,就会使得Reused Key Attack成为可能
  647. 同时通过收集大量的数据包,找到相同的IV,构造出相同的CRC-32校验值,也可以成功实施Bit-flipping Attack
  648. 破解WEP的理论变得可行了
  649. Berkly的Nikita Borisov,Ian Goldberg以及David Wagner共同完成了一篇很好的论文Security of the WEP algorithm,其中深入阐述了WEP破解的理论基础
  650. http://www.isaac.cs.berkeley.edu/isaac/wep-faq.html
  651. 实际破解WEP的步骤要稍微复杂一些,Aircrack实现了这一过程
  652. * 加载目标
  653. * 与目标网络进行协商
  654. * 生成密钥流
  655. * 构造ARP包
  656. * 生成自己的ARP包
  657. * 开始暴破
  658. 最终成功破解出WEP的KEY,可以免费蹭网了
  659. 11.4ECB模式的缺陷」
  660. 前面讲到了流密码加密算法中的几种常见的攻击方法,在分组加密算法中,也有一些可能被攻击者利用的地方
  661. 如果开发者不熟悉这些问题,就有可能错误地使用加密算法,导致安全隐患
  662. 对于分组加密算法来说,除去算法本身,还有一些通用的加密模式,不同的加密算法会支持同样的几种加密模式
  663. 常见的加密模式
  664. ECB
  665. CBC
  666. CFB
  667. OFB
  668. CTR
  669. ...
  670. 如果加密模式被攻击,那么不论加密算法的密钥有多长,都可能不再安全
  671. ECB模式(电码簿模式)是最简单的一种加密模式,它的每个分组之间相对独立
  672. 但ECB模式最大的问题也是出在这种分组的独立性上
  673. 攻击者只需要对调任意分组的密文,在经过解密后,所得明文的顺序也是经过对调的3-DES每个分组为8个字节
  674. 对比plain加密后的密文,可以看到,仅仅block 1的密文不同,而block 2的密文是完全一样的
  675. 也就是说,block 1并未影响到block 2的结果
  676. 这与链式加密模式(CBC)等是完全不同的,链式加密模式的分组前后之间会互相关联,一个字节的变化,会导致整个密文发生变化
  677. 这一特点也可以用于判断密文是否是用ECB模式加密的
  678. 对于ECB模式来说,改变分组密文的顺序,将改变解密后的明文顺序,替换某个分组密文,解密后该对应分组的明文也会被替换,而其他分组不受影响
  679. ECB模式并未完全混淆分组间的关系,因此当分组足够多时,仍然会暴露一些私密信息,而链式模式则避免了此问题
  680. 当需要加密的明文多于一个分组的长度时,应该避免使用ECB模式,而使用其他更加安全的加密模式
  681. 11.5Padding Oracle Attack」
  682. 在Eurocrypt 2002 大会上,Vaudenay介绍了针对CBC模式的Padding Oracle Attack
  683. 它可以在不知道密钥的情况下,通过对padding bytes的尝试,还原明文,或者构造出任意明文的密文
  684. 2010 年的BlackHat欧洲大会上,Juliano Rizzo与Thai Duong介绍了Padding Oracle在实际中的攻击案例
  685. http://net.ifera.com/research/
  686. 并公布了ASP.NET存在的Padding Oracle问题
  687. http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-3332
  688. 2011年的Pwnie Rewards中,ASP.NET的这个漏洞被评为最具价值的服务器端漏洞
  689. http://pwnies.com/winners
  690. 分组加密算法在实现加/解密时,需要把消息进行分组(block),block的大小常见的有
  691. 64bit
  692. 128bit
  693. 256bit
  694. 在解密完成后,如果最后的padding值不正确,解密程序往往会抛出异常(padding error)
  695. 而利用应用的错误回显,攻击者往往可以判断出padding是否正确
  696. 所以Padding Oracle实际上是一种边信道攻击,攻击者只需要知道密文的解密结果是否正确即可,而这往往有许多途径
  697. 比如在Web应用中,如果是padding不正确,则应用程序很可能会返回500的错误,如果padding正确,但解密出来的内容不正确,则可能会返回200的自定义错误
  698. 正确的padding值只可能为
  699. 1个字节的padding为0x01
  700. 2个字节的padding为0x02,0x02
  701. 3个字节的padding为0x03,0x03,0x03
  702. 4个字节的padding为0x04,0x04,0x04,0x04
  703. 因此慢慢调整IV的值,以希望解密后,最后一个字节的值为正确的padding byte,比如一个0x01
  704. 因为Intermediary Value是固定的(我们此时不知道Intermediary Value的值是多少),因此从0x000xFF之间,只可能有一个值与Intermediary Value的最后一个字节进行XOR后,结果是0x01
  705. 通过遍历这255个值,可以找出IV需要的最后一个字节
  706. 通过XOR运算,可以马上推导出此Intermediary Byte的值
  707. 在正确匹配了padding为0x01后,需要做的是继续推导出剩下的Intermediary Byte
  708. 根据padding的标准,当需要padding两个字节时,其值应该为0x020x02
  709. 而我们已经知道了最后一个Intermediary Byte为0x3D,因此可以更新IV的第8个字节为0x3D ^ 0x02 = 0x3F,此时可以开始遍历IV的第7个字节(0x00~0xFF)
  710. 获得Intermediary Value后,通过与原来的IV进行XOR运算,即可得到明文
  711. 在这个过程中仅仅用到了密文和IV,通过对padding的推导,即可还原出明文,而不需要知道密钥是什么
  712. 而IV并不需要保密,它往往是以明文形式发送的
  713. 如何通过Padding Oracle使得密文能够解密为任意明文呢
  714. 实际上通过前面的解密过程可以看出,通过改变IV,可以控制整个解密过程
  715. 因此在已经获得了Intermediary Value的情况下,很快就可以通过XOR运算得到可以生成任意明文的IV
  716. 而对于多个分组的密文来说,从最后一组密文开始往前推
  717. 以两个分组为例,第二个分组使用的IV是第一个分组的密文(cipher text),因此当推导出第二个分组使用的IV时,将此IV值当做第一个分组的密文,再次进行推导
  718. Brian Holyfield实现了一个叫padbuster的工具,可以自动实施Padding Oracle攻击
  719. http://bole.gdssecurity.com/labs/2010/9/14/automated-padding-oracle-attacks-with-padbuster.html
  720. http://github.com/GDSSecurity/PadBuster
  721. http://hi.baidu.com/aullik5/blog/item/7e769d2ec68b2d241f3089ce.html
  722. Padding Oracle Attack的关键在于攻击者能够获知解密的结果是否符合padding
  723. 在头现和使用CBC模式的分组加密算法时,注意这一点即可
  724. 11.6密钥管理」
  725. 密码学基本原则
  726. 密码系统的安全性应该依赖于密钥的复杂性,而不应该依赖于算法的保密性
  727. 在安全领域里,选择一个足够安全的加密算法不是困难的事情,难的是密钥管理
  728. 在一些实际的攻击案例中,直接攻击加密算法本身的案例很少,而因为密钥没有妥善管理导致的安全事件却很多
  729. 对于攻击者来说,他们不需要正面破解加密算法,如果能够通过一些方法获得密钥,则是件事半功倍的事情
  730. 密钥管理中最常见的错误,就是将密钥硬编码在代码里
  731. 同样的,将加密密钥、签名的salt等key硬编码在代码中,是非常不好的习惯
  732. 硬编码的密钥,在以下几种情况下可能被泄露
  733. * 代码被广泛传播
  734. 这种泄露途径常见于一些开源软件
  735. 有的商业软件并不开源,但编译后的二进制文件被用户下载,也可能被逆向工程反编译后,泄露硬编码的密钥
  736. * 软件开发团队的成员都能查看代码,从而获知硬编码的密钥
  737. 开发团队的成员如果流动性较大,则可能会由此泄露代码
  738. 对于第一种情况,如果一定要将密钥硬编码在代码中,我们尚可通过Diffie-Hellman交换密钥体系,生成公私钥来完成密钥的分发
  739. 对于第二种情况,则只能通过改善密钥管理来保护密钥
  740. 对于Web应用来说,常见的做法是将密钥(包括密码)保存在配置文件或者数据库中,在使用时由程序读出密钥并加载进内存
  741. 密钥所在的配置文件或数据库需要严格的控制访问权限,同时也要确保运维或DBA中具有访问权限的人越少越好
  742. 在应用发布到生产环境时,需要重新生成新的密钥或密码,以免与测试环境中使用的密钥相同
  743. 当黑客已经入侵之后,密钥管理系统也难以保证密钥的安全性
  744. 比如攻击者获取了一个webshell,那么攻击者也就具备了应用程序的一切权限
  745. 由于正常的应用程序也需要使用密钥,因此对密钥的控制不可能限制住webshell的正常请求
  746. 密钥管理的主要目的,还是为了防止密钥从非正常的渠道泄露
  747. 定期更换密钥也是一种有效的做法
  748. 一个比较安全的密钥管理系统,可以将所有的密钥(包括一些敏感配置文件)都集中保存在一个服务器(集群)上,并通过Web Service的方式提供获取密钥的API
  749. 每个Web应用在需要使用密钥时,通过带认证信息的API请求密钥管理系统,动态获取密钥
  750. Web应用不能把密钥写入本地文件中,只加载到内存,这样动态获取密钥最大程度地保护了密钥的私密性
  751. 密钥集中管理,降低了系统对于密钥的耦合性,也有利于定期更换密钥
  752. 11.7伪随机数问题」
  753. 伪随机数(pseudo random number)问题——伪随机数不够随机,是程序开发中会出现的一个问题
  754. 一方面,大多数开发者对此方面的安全知识有所欠缺,很容易写出不安全的代码,另一方面,伪随机数问题的攻击方式在多数情况下都只存在于理论中,难以证明,因此在说服程序员修补代码时也显得有点理由不够充分
  755. 但伪随机数问题是真实存在的、不可忽视的一个安全问题
  756. 伪随机数,是通过一些数学算法生成的随机数,并非真正的随机数
  757. 密码学上的安全伪随机数应该是不可压缩的
  758. 真随机数,则是通过一些物理系统生成的随机数,比如电压的波动、硬盘磁头读/写时的寻道时间、空中电磁波的噪声
  759. 11.7.1弱伪随机数的麻烦
  760. Luciano Bello发现了Debian上的OpenSSL包中存在弱伪随机数算法
  761. 产生这个问题的原因,是由于编译时会产生警告(warning)信息,因此下面的代码被移除了
  762. 这直接导致的后果是,在OpenSSL的伪随机数生成算法中,唯一的随机因子是pid
  763. 而在Linux系统中,pid的最大值也是32768
  764. 这是一个很小的范围,因此可以很快地遍历出所有的随机数
  765. 受到影响的有,从2006.92008.5.13的debian平台上生成的所有ssh key的个数是有限的,都是可以遍历出来的,这是一个非常严重的漏洞
  766. 同时受到影响的还有OpenSSL生成的key以及OpenVPN生成的key
  767. Debian随后公布了这些可以被遍历的key的名单
  768. 这次事件的影响很大,也让更多的开发者开始关注伪随机数的安全问题
  769. 在Web应用中,使用伪随机数的地方非常广泛
  770. 密码、key、SessionID、token等许多非常关键的secret往往都是通过伪随机数算法生成的
  771. 如果使用了弱伪随机数算法,则可能会导致非常严重的安全问题
  772. 11.7.2时间真的随机吗
  773. 很多伪随机数算法与系统时间有关,而有的程序员甚至就直接使用系统时间代替随机数的生成,这样生成的随机数,是根据时间顺序增长的,可以从时间上进行预测,从而存在安全隐患
  774. 比如下面这段代码,其逻辑是用户取回密码时,会由系统随机生成一个新的密码,并发送到用户邮箱
  775. ----------------------------------------------------------------------------------------
  776. function sendPSW()
  777. {
  778. ......
  779. $messenger = &$this->system->loadModel('system/messenger');echo microtime()."<br/>";
  780. $passwd = substr(md5(print_r(microtime(),true)),0,6);
  781. ......
  782. }
  783. ----------------------------------------------------------------------------------------
  784. 这个新生成的$passwd,是直接调用了microtime()后,取其MD5值的前6
  785. 由于MD5算法是单向的哈希函数,因此只需要遍历microtime()的值,再按照同样的算法,即可猜解出$passwd的值
  786. PHP中的microtime()由两个值合并而成,一个是微秒数,一个是系统当前秒数
  787. 因此只需要获取到服务器的系统时间,就可以以此时间为基数,按次序递增,即可猜解出新生成的密码
  788. 因此这个算法是存在非常严重的设计缺陷的,程序员预想的随机生成密码,其实并未随机
  789. {在开发程序时,要切记不要把时间函数当成随机数使用}
  790. 11.7.3破解伪伪随机数算法的种子
  791. 在PHP中,常用的随机数生成算法有mnd()、mt_rand()
  792. 可见,rand()的范围其实是非常小的,如果使用rand()生成的随机数用于一些重要的地方,则会非常危险
  793. 其实PHP中的mt_rand()也不是很安全,Stefan Esser在他著名的papermt_srand and not so random numbers中提出了PHP的伪随机函数mt_rand()在实现上的一些缺陷
  794. http://www.suspekt.org/2008/8/17/mt_srand-and-not-so-ranfom-numbers/
  795. 伪随机数是由数学算法实现的,它真正随机的地方在于种子(seed)
  796. 种子一旦确定后,再通过同一伪随机数算法计算出来的随机数,其值是固定的,多次计算所得值的顺序也是固定的
  797. 在PHP4.2.0之前的版本中,是需要通过srand()或mt_srand()给rand()、mt_rand()播种的
  798. 在PHP 4.2.0之后的版本中不再需要事先通过srand()、mt_srand()播种
  799. 比如直接调用mt_rand(),系统会自动播种
  800. 在PHP 4.2.0之后的版本中,如果没有通过播种函数指定seed,而直接调用mt_rand(),则系统会分配一个默认的种子
  801. 32位系统上默认的播种的种子最大值是2^32,因此最多只需要尝试2^32次就可以破解seed
  802. 可以看出,当seed确定时,第一次到第n次通过mt_rand()产生的值都没有发生变化
  803. 建立在这个基础上,就可以得到一种可行的攻击方式
  804. * 通过一些方法猜解出种子的值
  805. * 通过mt_srand()对猜解出的种子值进行播种
  806. * 通过还原程序逻辑,计算出对应的mt_rand()产生的伪随机数的值
  807. 需要注意的是,在PHP 5.2.1及其之后的版本中调整了随机数的生成算法,但强度未变,因此在实施猜解种子时,需要在对应的PHP版本中运行猜解程序
  808. 在Stefan Esser的文中还提到了一个小技巧,可以通过发送Keep-Alive HTTP头,迫使服务器端使用同一PHP进程响应请求,而在该PHP进程中,随机数在使用时只会在一开始播种一次
  809. 在一个Web应用中,有很多地方都可以获取到随机数,从而提供猜解种子的可能
  810. Stefan Esser提供了一种Cross Application Attacks的思路,即通过前一个应用在页面上返回的随机数值,猜解出其他应用生成的随机数值
  811. 如果服务器端将$search_id返回到页面上,则攻击者就可能猜解出当前的种子
  812. 这种攻击确实可行,比如一个服务器上同时安装了WordPress与phpBB,可以通过phpBB猜解出种子,然后利用WordPress的密码取回功能猜解出新生成的密码
  813. Stefan Esser描述这个攻击过程如下
  814. * 使用Keep-Alive HTTP请求在phpBB2论坛中搜索字符串'a'
  815. * 搜索必然会出来很多结果,同时也泄露了search_id
  816. * 很容易通过该值猜解出随机数的种子
  817. * 攻击者仍然使用Keep-Alive HTTP头发送一个重置admin密码的请求给WordPress blog
  818. * WordPress mt_rand()生成确认链接,并发送到管理员邮箱
  819. * 攻击者根据已算出的种子,可以构造出此确认链接
  820. * 攻击者确认此链接(仍然使用Keep-Alive头),WordPress将向管理员邮箱发送新生成的密码
  821. * 因为新密码也是由mt_rand()生成的,攻击者仍然可以计算出来
  822. * 从而攻击者最终获取了新的管理员密码
  823. 11.7.4使用安全的随机数
  824. 我们需要谨记,在重要或敏感的系统中,一定要使用足够强壮的随机数生成算法
  825. 在Java中,可以使用java.security.SecureRandom
  826. 而在Linux中,可以使用/dev/random或者/dev/urandom来生成随机数,只需要读取即可
  827. 而在PHP 5.3.0及其之后的版本中,若是支持openSSL扩展,也可以直接使用函数来生成随机数
  828. 除了以上方法外,从算法上还可以通过多个随机数的组合,以增加随机数的复杂性
  829. 比如通过给随机数使用MD5算法后,再连接一个随机字符,然后再使用MD5算法一次
  830. 这些方法,也将极大地增加攻击的难度
  831. 11.8总结」
  832. 在加密算法的选择和使用上,有以下最佳实践
  833. * 不要使用ECB模式
  834. * 不要使用流密码(比如RC4)
  835. * 使用HMAC-SHA1代替MD5(甚至是代替SHA1)
  836. * 不要使用相同的key做不同的事情
  837. * salts与IV需要随机产生
  838. * 不要自己实现加密算法,尽量使用安全专家已经实现好的库
  839. * 不要依赖系统的保密性
  840. 当你不知道该如何选择时,有以下建议
  841. * 使用CBC模式的AES256用于加密
  842. * 使用HMAC-SHA512用于完整性检查
  843. * 使用带salt的SHA-256 或SHA-512 用于Hashing

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

闽ICP备14008679号