【前言】

本文简单的介绍了加密技术相关概念,最后总结了java中现有的加密技术以及使用方法和例子

【最简单的加密】

1.简单的概念

明文:加密前的信息

密文:机密后的信息

算法:加密或解密的算法

密钥:算法使用的钥匙(读作miyao,正确应该是miyue,但是大家都读miyao)

2.简单的例子

将123456每位数字都加1后得到234567,

其中123456就是明文,234567就是密文,加密密钥就是1,加密算法是每位加

3.对称加密和非对称加密

以上为例,

123456-->234567的加密密钥就是1,加密算法是每位+

234567-->123456的解密密钥也是1,解密算法是每位-

其中加密算法(+)和解密算法(-)相对称,这种加密算法就称作对称加密,

同样,如果加密算法和解密算法不对称就称之为非对称加密。

4.算法举例

众多的加密手段大致可以分为单项加密和双向加密。单项加密指通过对数据进行摘要计算生成密文,密文不可逆推还原,比如有Base64、MD5、SHA等;双向加密则相反,指可以把密文逆推还原成明文,其中双向加密又分为对称加密和非对称加密。对称加密是指数据使用者必须拥有同样的密钥才可以进行加密解密,就像大家共同约定了一组暗号一样,对称加密的手段有DES、3DES、AES、IDEA、RC4、RC5等;而非对称加密相对于对称加密而言,无需拥有同一组密钥,它是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能进行解密。此类的加密手段有RSA、DSA等

对称加密算法:DES算法,3DES算法,TDEA算法,Blowfish算法,RC5算法,IDEA算法,AES算法。

非对称加密算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC。

经典的哈希算法:MD2、MD4、MD5 和 SHA-1(目的是将任意长输入通过算法变为固定长输出,且保证输入变化一点输出都不同,且不能反向解密)

5.经典算法实现

5.1:AES算法

packagecom.meng.study.security;importjava.security.SecureRandom;importjavax.crypto.Cipher;importjavax.crypto.KeyGenerator;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;public classAESUtil {/*** AES加密

*

*@paramcontent

* 待加密的内容

*@paramencryptKey

* 加密密钥

*@return加密后的byte[]

*@throwsException*/

public static byte[] aesEncryptToBytes(String content, String encryptKey) throwsException {

KeyGenerator kgen= KeyGenerator.getInstance("AES");

SecureRandom random= SecureRandom.getInstance("SHA1PRNG");

random.setSeed(encryptKey.getBytes());

kgen.init(128, random);

SecretKey secretKey= new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");

Cipher cipher= Cipher.getInstance("AES");

cipher.init(Cipher.ENCRYPT_MODE, secretKey);return cipher.doFinal(content.getBytes("UTF-8"));

}/*** AES加密为base 64 code

*

*@paramcontent

* 待加密的内容

*@paramencryptKey

* 加密密钥

*@return加密后的base 64 code

*@throwsException*/

public static String aesEncrypt(String content, String encryptKey) throwsException {returnBASE64Util.base64Encode(aesEncryptToBytes(content, encryptKey));

}/*** AES解密

*

*@paramencryptBytes

* 待解密的byte[]

*@paramdecryptKey

* 解密密钥

*@return解密后的String

*@throwsException*/

public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throwsException {

KeyGenerator kgen= KeyGenerator.getInstance("AES");

SecureRandom random= SecureRandom.getInstance("SHA1PRNG");

random.setSeed(decryptKey.getBytes());

kgen.init(128, random);

SecretKey secretKey= new SecretKeySpec(kgen.generateKey().getEncoded(), "AES");

Cipher cipher= Cipher.getInstance("AES");

cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decryptBytes =cipher.doFinal(encryptBytes);return newString(decryptBytes);

}/*** 将base 64 code AES解密

*

*@paramencryptStr

* 待解密的base 64 code

*@paramdecryptKey

* 解密密钥

*@return解密后的string

*@throwsException*/

public static String aesDecrypt(String encryptStr, String decryptKey) throwsException {returnaesDecryptByBytes(BASE64Util.base64Decode(encryptStr), decryptKey);

}

}

显示代码

5.2:3DES算法

packagecom.meng.study.security;importjava.io.UnsupportedEncodingException;importjavax.crypto.Cipher;importjavax.crypto.SecretKey;importjavax.crypto.spec.SecretKeySpec;importorg.apache.log4j.Logger;importcom.meng.study.cache.GuavaCacheUtil;/***

*@authorzhenbinmeng

**/

public classDESUtil {private static Logger logger = Logger.getLogger(DESUtil.class);//定义加密算法,DESede(即3DES)

private static final String DESede = "DESede";private static final String PASSWORD_CRYPT_KEY = "2015mengzhenbinStudyForSecurity@DESede";/*** 加密方法

*

*@paramsrc

* 源数据的字节数组

*@return

*/

public static byte[] encryptMode(byte[] src) {try{

SecretKey deskey= new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); //生成密钥

Cipher c1 = Cipher.getInstance(DESede); //实例化负责加密/解密的Cipher工具类

c1.init(Cipher.ENCRYPT_MODE, deskey); //初始化为加密模式

returnc1.doFinal(src);

}catch(Exception e) {

logger.error("DesUtil.encryptMode error", e);

e.printStackTrace();

}return null;

}/*** 加密方法(BASE64编码返回)

*

*@paramsrc

* 源数据的字节数组

*@return

*/

public static String encryptModeBase64(byte[] src) {try{

SecretKey deskey= new SecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede); //生成密钥

Cipher c1 = Cipher.getInstance(DESede); //实例化负责加密/解密的Cipher工具类

c1.init(Cipher.ENCRYPT_MODE, deskey); //初始化为加密模式

returnBASE64Util.base64Encode(c1.doFinal(src));

}catch(Exception e) {

logger.error("DesUtil.encryptMode error", e);

e.printStackTrace();

}return null;

}/*** 解密函数

*

*@paramsrc

* 密文的字节数组

*@return

*/

public static byte[] decryptMode(byte[] src) {try{

SecretKey deskey= newSecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);

Cipher c1=Cipher.getInstance(DESede);

c1.init(Cipher.DECRYPT_MODE, deskey);//初始化为解密模式

returnc1.doFinal(src);

}catch(Exception e) {

logger.error("DesUtil.decryptMode error", e);

e.printStackTrace();

}return null;

}/*** 解密函数(BASE64解码后解密)

*

*@paramsrc

* 密文的字节数组

*@return

*/

public staticString decryptModeBase64(String src) {try{

SecretKey deskey= newSecretKeySpec(build3DesKey(PASSWORD_CRYPT_KEY), DESede);

Cipher c1=Cipher.getInstance(DESede);

c1.init(Cipher.DECRYPT_MODE, deskey);//初始化为解密模式

return newString(c1.doFinal(BASE64Util.base64Decode(src)));

}catch(Exception e) {

logger.error("DesUtil.decryptMode error", e);

e.printStackTrace();

}return null;

}/** 根据字符串生成密钥字节数组

*

* @param keyStr 密钥字符串

*

* @return

*

* @throws UnsupportedEncodingException*/

public static byte[] build3DesKey(String keyStr) throwsUnsupportedEncodingException {byte[] key = new byte[24]; //声明一个24位的字节数组,默认里面都是0

byte[] temp = keyStr.getBytes("UTF-8"); //将字符串转成字节数组

/** 执行数组拷贝 System.arraycopy(源数组,从源数组哪里开始拷贝,目标数组,拷贝多少位)*/

if (key.length >temp.length) {//如果temp不够24位,则拷贝temp数组整个长度的内容到key数组中

System.arraycopy(temp, 0, key, 0, temp.length);

}else{//如果temp大于24位,则拷贝temp数组24个长度的内容到key数组中

System.arraycopy(temp, 0, key, 0, key.length);

}returnkey;

}

}

显示代码

5.3:MD5算法

packagecom.meng.study.security;importjava.security.MessageDigest;public classMD5Util {/*** 获取byte[]的md5值

*

*@parambytes

* byte[]

*@returnmd5

*@throwsException*/

public static byte[] md5(byte[] bytes) throwsException {

MessageDigest md= MessageDigest.getInstance("MD5");

md.update(bytes);returnmd.digest();

}/*** 获取字符串md5值

*

*@parammsg

*@returnmd5

*@throwsException*/

public static byte[] md5(String msg) throwsException {returnmd5(msg.getBytes());

}/*** 获取字符串md5值

*

*@parammsg

*@returnmd5

*@throwsException*/

public static String md5Hex(String msg) throwsException {byte[] messageDigest =md5(msg.getBytes());//Create Hex String

StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数

for (int i = 0; i < messageDigest.length; i++) {

String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {

hexString.append(0);

}

hexString.append(shaHex);

}returnhexString.toString();

}/*** 结合base64实现md5加密

*

*@parammsg

* 待加密字符串

*@return获取md5后转为base64

*@throwsException*/

public static String md5Base64(String msg) throwsException {returnBASE64Util.base64Encode(md5(msg));

}

}

显示代码

5.4:SHA算法

packagecom.meng.study.security;importjava.security.MessageDigest;public classSHAUtil {public staticString SHA1(String decript) {try{

MessageDigest digest= java.security.MessageDigest.getInstance("SHA-1");

digest.update(decript.getBytes());byte messageDigest[] =digest.digest();//Create Hex String

StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数

for (int i = 0; i < messageDigest.length; i++) {

String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {

hexString.append(0);

}

hexString.append(shaHex);

}returnhexString.toString();

}catch(Exception e) {

e.printStackTrace();

}return "";

}public staticString SHA(String decript) {try{

MessageDigest digest= java.security.MessageDigest.getInstance("SHA");

digest.update(decript.getBytes());byte messageDigest[] =digest.digest();//Create Hex String

StringBuffer hexString = newStringBuffer();//字节数组转换为 十六进制 数

for (int i = 0; i < messageDigest.length; i++) {

String shaHex= Integer.toHexString(messageDigest[i] & 0xFF);if (shaHex.length() < 2) {

hexString.append(0);

}

hexString.append(shaHex);

}returnhexString.toString();

}catch(Exception e) {

e.printStackTrace();

}return "";

}

}

显示代码

5.5:RSA算法

packagecom.meng.study.security;importjava.math.BigInteger;importjava.security.KeyFactory;importjava.security.KeyPair;importjava.security.KeyPairGenerator;importjava.security.NoSuchAlgorithmException;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.security.spec.RSAPrivateKeySpec;importjava.security.spec.RSAPublicKeySpec;importjava.util.HashMap;importjavax.crypto.Cipher;public classRSAUtil {/*** 生成公钥和私钥

*

*@throwsNoSuchAlgorithmException

**/

public static HashMap getKeys() throwsNoSuchAlgorithmException {

HashMap map = new HashMap();

KeyPairGenerator keyPairGen= KeyPairGenerator.getInstance("RSA");

keyPairGen.initialize(1024);

KeyPair keyPair=keyPairGen.generateKeyPair();

RSAPublicKey publicKey=(RSAPublicKey) keyPair.getPublic();

RSAPrivateKey privateKey=(RSAPrivateKey) keyPair.getPrivate();

map.put("public", publicKey);

map.put("private", privateKey);returnmap;

}/*** 使用模和指数生成RSA公钥

* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA

* /None/NoPadding】

*

*@parammodulus

* 模

*@paramexponent

* 指数

*@return

*/

public staticRSAPublicKey getPublicKey(String modulus, String exponent) {try{

BigInteger b1= newBigInteger(modulus);

BigInteger b2= newBigInteger(exponent);

KeyFactory keyFactory= KeyFactory.getInstance("RSA");

RSAPublicKeySpec keySpec= newRSAPublicKeySpec(b1, b2);return(RSAPublicKey) keyFactory.generatePublic(keySpec);

}catch(Exception e) {

e.printStackTrace();return null;

}

}/*** 使用模和指数生成RSA私钥

* 注意:【此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同,如Android默认是RSA

* /None/NoPadding】

*

*@parammodulus

* 模

*@paramexponent

* 指数

*@return

*/

public staticRSAPrivateKey getPrivateKey(String modulus, String exponent) {try{

BigInteger b1= newBigInteger(modulus);

BigInteger b2= newBigInteger(exponent);

KeyFactory keyFactory= KeyFactory.getInstance("RSA");

RSAPrivateKeySpec keySpec= newRSAPrivateKeySpec(b1, b2);return(RSAPrivateKey) keyFactory.generatePrivate(keySpec);

}catch(Exception e) {

e.printStackTrace();return null;

}

}/*** 公钥加密

*

*@paramdata

*@parampublicKey

*@return*@throwsException*/

public static String encryptByPublicKey(String data, RSAPublicKey publicKey) throwsException {

Cipher cipher= Cipher.getInstance("RSA");

cipher.init(Cipher.ENCRYPT_MODE, publicKey);//模长

int key_len = publicKey.getModulus().bitLength() / 8;//加密数据长度 <= 模长-11

String[] datas = splitString(data, key_len - 11);

String mi= "";//如果明文长度大于模长-11则要分组加密

for(String s : datas) {

mi+=bcd2Str(cipher.doFinal(s.getBytes()));

}returnmi;

}/*** 私钥解密

*

*@paramdata

*@paramprivateKey

*@return*@throwsException*/

public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throwsException {

Cipher cipher= Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, privateKey);//模长

int key_len = privateKey.getModulus().bitLength() / 8;byte[] bytes =data.getBytes();byte[] bcd =ASCII_To_BCD(bytes, bytes.length);//如果密文长度大于模长则要分组解密

String ming = "";byte[][] arrays =splitArray(bcd, key_len);for (byte[] arr : arrays) {

ming+= newString(cipher.doFinal(arr));

}returnming;

}/*** ASCII码转BCD码

**/

public static byte[] ASCII_To_BCD(byte[] ascii, intasc_len) {byte[] bcd = new byte[asc_len / 2];int j = 0;for (int i = 0; i < (asc_len + 1) / 2; i++) {

bcd[i]= asc_to_bcd(ascii[j++]);

bcd[i]= (byte) (((j >= asc_len) ? 0x00 : asc_to_bcd(ascii[j++])) + (bcd[i] << 4));

}returnbcd;

}public static byte asc_to_bcd(byteasc) {bytebcd;if ((asc >= '0') && (asc <= '9'))

bcd= (byte) (asc - '0');else if ((asc >= 'A') && (asc <= 'F'))

bcd= (byte) (asc - 'A' + 10);else if ((asc >= 'a') && (asc <= 'f'))

bcd= (byte) (asc - 'a' + 10);elsebcd= (byte) (asc - 48);returnbcd;

}/*** BCD转字符串*/

public static String bcd2Str(byte[] bytes) {char temp[] = new char[bytes.length * 2], val;for (int i = 0; i < bytes.length; i++) {

val= (char) (((bytes[i] & 0xf0) >> 4) & 0x0f);

temp[i* 2] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

val= (char) (bytes[i] & 0x0f);

temp[i* 2 + 1] = (char) (val > 9 ? val + 'A' - 10 : val + '0');

}return newString(temp);

}/*** 拆分字符串*/

public static String[] splitString(String string, intlen) {int x = string.length() /len;int y = string.length() %len;int z = 0;if (y != 0) {

z= 1;

}

String[] strings= new String[x +z];

String str= "";for (int i = 0; i < x + z; i++) {if (i == x + z - 1 && y != 0) {

str= string.substring(i * len, i * len +y);

}else{

str= string.substring(i * len, i * len +len);

}

strings[i]=str;

}returnstrings;

}/*** 拆分数组*/

public static byte[][] splitArray(byte[] data, intlen) {int x = data.length /len;int y = data.length %len;int z = 0;if (y != 0) {

z= 1;

}byte[][] arrays = new byte[x +z][];byte[] arr;for (int i = 0; i < x + z; i++) {

arr= new byte[len];if (i == x + z - 1 && y != 0) {

System.arraycopy(data, i* len, arr, 0, y);

}else{

System.arraycopy(data, i* len, arr, 0, len);

}

arrays[i]=arr;

}returnarrays;

}

}

显示代码

5.6:Base64算法

packagecom.meng.study.security;importsun.misc.BASE64Decoder;importsun.misc.BASE64Encoder;

@SuppressWarnings("restriction")public classBASE64Util {/*** base 64 encode

*

*@parambytes

* 待编码的byte[]

*@return编码后的base 64 code*/

public static String base64Encode(byte[] bytes) {return newBASE64Encoder().encode(bytes);

}/*** base 64 decode

*

*@parambase64Code

* 待解码的base 64 code

*@return解码后的byte[]

*@throwsException*/

public static byte[] base64Decode(String base64Code) throwsException {return newBASE64Decoder().decodeBuffer(base64Code);

}

}

显示代码

5.7:测试代码

packagecom.meng.study.security;importjava.security.interfaces.RSAPrivateKey;importjava.security.interfaces.RSAPublicKey;importjava.util.HashMap;/*** 编码工具类 1.将byte[]转为各种进制的字符串 2.base 64 encode 3.base 64 decode

*

*@authoruikoo9

*@version0.0.5.20140601*/

public classEncodeUtilTest {public static void main(String[] args) throwsException {

String msg= "我爱你";

System.out.println("转换前:" +msg);//==Base64==

String base64Str =BASE64Util.base64Encode(msg.getBytes());

System.out.println("Base64转换后:" +base64Str);

System.out.println("Base64解码后:" + newString(BASE64Util.base64Decode(base64Str)));//==Md5==

String md5Base64Str =MD5Util.md5Base64(msg);

System.out.println("Md5后Base编码转换后:" +md5Base64Str);//==Des==

byte[] des =DESUtil.encryptMode(msg.getBytes());

System.out.println("【DES加密后】:" + newString(des));byte[] myMsgArr =DESUtil.decryptMode(des);

System.out.println("【DES解密后】:" + newString(myMsgArr));

String desBase64Str=DESUtil.encryptModeBase64(msg.getBytes());

System.out.println("Des后Base64编码转换后:" +desBase64Str);

System.out.println("Base64解码后Des转换后:" + newString(DESUtil.decryptModeBase64(desBase64Str)));//==Aes==

String aesKey = "123456";

String aesEnStr=AESUtil.aesEncrypt(msg,aesKey);

System.out.println("【AES加密Base64编码后】:" +aesEnStr);

String aesDeStr=AESUtil.aesDecrypt(aesEnStr,aesKey);

System.out.println("【Base64解码AES解密后】:" +aesDeStr);//==Rsa==

HashMap keys =RSAUtil.getKeys();

RSAPublicKey publicKey= (RSAPublicKey) keys.get("public");

RSAPrivateKey privateKey= (RSAPrivateKey) keys.get("private");

RSAPublicKey pubKey=RSAUtil.getPublicKey(publicKey.getModulus().toString(), publicKey.getPublicExponent().toString());

RSAPrivateKey priKey=RSAUtil.getPrivateKey(privateKey.getModulus().toString(), privateKey.getPrivateExponent().toString());

String rsaEnStr=RSAUtil.encryptByPublicKey(msg, pubKey);

System.out.println("【RSA公钥加密后】:" +rsaEnStr);

String rsaDeStr=RSAUtil.decryptByPrivateKey(rsaEnStr, priKey);

System.out.println("【RSA私钥解密后】:" +rsaDeStr);

}

}

显示代码

java解密_JAVA加解密相关推荐

  1. Java 3desede加解密_JAVA加解密11-对称加密算法-DES以及DESede算法

    一.简述 对称加密算法就是能将数据加解密.加密的时候用密钥对数据进行加密,解密的时候使用同样的密钥对数据进行解密. DES是美国国家标准研究所提出的算法.因为加解密的数据安全性和密钥长度成正比.des ...

  2. rsa java代码_java加解密RSA使用方法代码示例

    最近为了分析一段请求流,不得不去研究一下RSA加密. 首先,强调一点:密钥的"钥"读"yue",不是"yao",额... 网上关于RSA的原 ...

  3. 一个java的DES加解密类转换成C#

    原文:一个java的DES加解密类转换成C# 一个java的des加密解密代码如下: //package com.visionsky.util;import java.security.*; //im ...

  4. Java使用AES加解密

    Java使用AES加解密 目录 1.1生成密钥 1.2密钥的存储 1.3获取存储的密钥 1.4加解密 1.5使用存储的密钥进行加解密示例 AES是一种对称的加密算法,可基于相同的密钥进行加密和解密.J ...

  5. JAVA:实现XXTea加解密算法(附完整源码)

    JAVA:实现XXTea加解密算法 public class XXTEAprivate XXTEA() {}public static byte[] encrypt(byte[] data, byte

  6. java实现DES加解密算法

    以下是我用java实现的DES算法,实现中可能存在一点问题自己没空去找,但我觉得DES的算法过程肯定没错!现在暂时没时间去找到底是哪里的问题,有空再瞧瞧自己的代码喽! makekey.java是生成密 ...

  7. java加密解密代码_java加解密文件公用方法整合(多看一本书,少写三行代码)

    最近接到任务(文件的安全性)需要在文件上传到服务器上时将文件加密保存, 用户下载时将文件解密后返回给用户.翻了下方法最后决定用java中的Cipher类来完成(里面的实现方式挺全的). 上手实现.po ...

  8. java sha加解密算法_java加解密

    SHA256 ------------------java自带实现方式--------------- package com.xiayu.demo; import java.io.Unsupporte ...

  9. Java 进行 RSA 加解密时不得不考虑到的那些事儿

    1. 加密的系统不要具备解密的功能,否则 RSA 可能不太合适 公钥加密,私钥解密.加密的系统和解密的系统分开部署,加密的系统不应该同时具备解密的功能,这样即使黑客攻破了加密系统,他拿到的也只是一堆无 ...

最新文章

  1. oracle缺少key xe.reg,【Oracle XE系列之一】Windows 7 64位安裝Oracle XE(32位)數據庫(REG_XE報錯、字符集、修改8080端口等)...
  2. php mb strimwidth,wordpress截断函数mb_strimwidth()失效的解决方法
  3. php 定时缓存,php如何定时删除缓存??
  4. boost::mp11::mp_compose相关用法的测试程序
  5. 关于Vue中计算属性computed和methods属性的区别,你了解多少呢
  6. 了解ADF Faces clientComponent属性
  7. 《敏捷可执行需求说明 Scrum提炼及实现技术》—— 3.4 关注干系人的“愿求”...
  8. 聚类的基本概念-聚类与分类的区别
  9. 图解TCPIP---第六章---传输层TCPUDP
  10. 操作系统--windows系列之windows8
  11. 2022年上半年网络工程师上午真题及答案
  12. 在死亡边缘疯狂试探:“黑暗旅游”,你敢尝试吗?
  13. IT行业为何如此吃香?2019学习IT就业前景分析
  14. OpenGL 实验一 绘制简单图形
  15. 爱心代码表白(可直接复制运行)
  16. solr dih有子查询时速度慢
  17. SCADA/EMS系统的子系统的划分
  18. Android Crash signal 4 (SIGILL), code 1 (ILL_ILLOPC), fault addr b56cb106
  19. 盈帆报表软件制作编号报表(报表工具)
  20. 链路聚合(端口聚合)

热门文章

  1. 游戏公司如何应对游戏黑产 ?
  2. 基于MDK-KILE5.23版本的STM32创建工程
  3. 手机通讯录系统(三层架构+JDBC+MySQL)
  4. python爬虫批量下载图片
  5. C++刷题知识点总结2
  6. 20层的试炼html5,Vue.js-02:新手村的试炼 - 新世界的武器(指令)
  7. python+matplotlib对柿子图的彩色和灰色直方图统计
  8. iOS Instrument使用之Core Animation(图形性能)
  9. Celery入门--定时任务的开发及运行
  10. Win 10 忘记密码不用U盘就可解决