2 changed files with 1709 additions and 0 deletions
@ -0,0 +1,576 @@ |
|||||||
|
#Java安全 |
||||||
|
##为什么要掌握Java安全? |
||||||
|
* 提升逼格,现在市场上的大部分程序员都对Java安全、数据加密等等一无所知,而现在的面试中很多面试官为了凸显自己的高逼格,总爱问你一些安全相关的问题。只有掌握了Java安全相关知识,才能跟面试官站在同一逼格线,进行愉快滴交流。 |
||||||
|
* 项目中到处需要。如:账号密码的加密,订单支付的加密,个人资料的加密等等。 |
||||||
|
* 初级工程师向中高级工程师进阶的必经之路。 |
||||||
|
##什么是加密? |
||||||
|
* 古老的加密方法:《潜伏》中的余则成,收到密码:12 25 13 15 29 19;《模仿游戏》,二战时期,德国的密码机及图灵为了破解德军密码而研制出第一代计算机(图灵机)。 |
||||||
|
* 对称加密和非对称加密等等。 |
||||||
|
* MD5,属于消息摘要(Message Digest)。 |
||||||
|
|
||||||
|
## 学习目标 |
||||||
|
1. 复习字节与字符、字符编码、进制转换、java里的io |
||||||
|
2. 一些基本的安全知识 |
||||||
|
3. 三大风险:窃听风险、篡改风险、冒充风险 |
||||||
|
4. 重放攻击(wpe) |
||||||
|
5. 常用加密算法(对称/非对称) |
||||||
|
6. 消息摘要 |
||||||
|
7. 数字签名 |
||||||
|
8. 数字证书 |
||||||
|
9. Keytool工具的使用 |
||||||
|
10. SSL/TLS的工作原理 |
||||||
|
11. Https双向认证原理 |
||||||
|
|
||||||
|
#凯撒密码 |
||||||
|
##第一个案例,对字符进行简单的加密。 |
||||||
|
* 对字符数组中所有的字符做+1处理(后面可以转换成+num这个数由通讯双方来协定) |
||||||
|
###代码 |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Camille |
||||||
|
*对字符简单的加密 |
||||||
|
*/ |
||||||
|
public class SimpleEncryptionDemo01 { |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
// 确定加密的内容 |
||||||
|
String content = "i love you tonight 404 see you z"; |
||||||
|
//加密 |
||||||
|
String encryptData = encrypt(content); |
||||||
|
System.out.println("加密后:" + encryptData); |
||||||
|
//解密 |
||||||
|
String decryptData = decrypt(encryptData); |
||||||
|
System.out.println("解密后:" + decryptData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密方法 |
||||||
|
* |
||||||
|
* @param content |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String encrypt(String content) { |
||||||
|
// 将内容转换成字符数组 |
||||||
|
char[] charArray = content.toCharArray(); |
||||||
|
// 遍历出所有字符 |
||||||
|
for (int i = 0; i < charArray.length; i++) { |
||||||
|
// 对所有字符进行 + 1操作 |
||||||
|
charArray[i] = (char) (charArray[i] + 1); |
||||||
|
} |
||||||
|
return new String(charArray); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解密方法 |
||||||
|
* |
||||||
|
* @param encryptData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String decrypt(String encryptData) { |
||||||
|
// 将内容转换成字符数组 |
||||||
|
char[] charArray = encryptData.toCharArray(); |
||||||
|
System.out.println(new String(charArray)); |
||||||
|
// 解密 |
||||||
|
for (int i = 0; i < charArray.length; i++) { |
||||||
|
charArray[i] = (char) (charArray[i] - 1); |
||||||
|
} |
||||||
|
return new String(charArray); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
##第二个案例,对字节进行简单的加密。 |
||||||
|
|
||||||
|
**字节和字符的区别?** |
||||||
|
* UTF-8编码下,一个英文或数字字符就是一个字节 |
||||||
|
* UTF-8编码下,一个汉字代表三个字节。 |
||||||
|
* 为什么new String(bytes)的时候回发生乱码,就是因为加密后得到的字节找不到对应的字符。 |
||||||
|
* Base64的原理 |
||||||
|
 |
||||||
|
|
||||||
|
###代码 |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* @author Camille |
||||||
|
*对字节进行加密 |
||||||
|
*/ |
||||||
|
public class SimpleEncryptionDemo2 { |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
// 测试字节字符 |
||||||
|
String content = "中文"; |
||||||
|
int key = 80; |
||||||
|
String encryptData = encrypt(content,key); |
||||||
|
System.out.println("+密后:" + encryptData); |
||||||
|
String decryptData = decrypt(encryptData,key); |
||||||
|
System.out.println("解密后:" + decryptData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密 |
||||||
|
* |
||||||
|
* @param content |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String encrypt(String content,int key) { |
||||||
|
// 第一步,转换成字节数组 |
||||||
|
byte[] bytes = content.getBytes(); |
||||||
|
System.out.println("打印未加密的字节数组:"); |
||||||
|
Util.printBytes(bytes); |
||||||
|
System.out.println("_________________________________________"); |
||||||
|
// 第二步,遍历出所有字节,并做+1处理 |
||||||
|
for (int i = 0; i < bytes.length; i++) { |
||||||
|
bytes[i] = (byte) (bytes[i] + key); |
||||||
|
} |
||||||
|
System.out.println("打印加密的字节数组:"); |
||||||
|
Util.printBytes(bytes); |
||||||
|
System.out.println("_________________________________________"); |
||||||
|
// return new String(bytes); |
||||||
|
return Base64.getEncoder().encodeToString(bytes); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解密 |
||||||
|
* @param encryptData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String decrypt(String encryptData,int key) { |
||||||
|
// 第一步,转换成字节数组,加密时使用Base64编码,那解密时也要使用Base64解码 |
||||||
|
byte[] bytes = Base64.getDecoder().decode(encryptData); |
||||||
|
// byte[] bytes = encryptData.getBytes(); |
||||||
|
System.out.println("打印经过两次转换后的字节数组:"); |
||||||
|
Util.printBytes(bytes); |
||||||
|
System.out.println("_________________________________________"); |
||||||
|
// 解密 |
||||||
|
for (int i = 0; i < bytes.length; i++) { |
||||||
|
bytes[i] = (byte) (bytes[i] - key); |
||||||
|
} |
||||||
|
System.out.println("打印解密后的字节数组:"); |
||||||
|
Util.printBytes(bytes); |
||||||
|
System.out.println("_________________________________________"); |
||||||
|
return new String(bytes); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
##对称加密与非对称加密 |
||||||
|
* 对称加密与非对称加密的区别 |
||||||
|
* 对称加密。同一把钥匙进行加密和解密 |
||||||
|
* 非对称加密,公钥加密,私钥解密。 |
||||||
|
|
||||||
|
##对称加密的案例 |
||||||
|
常见算法:AES、DES、3DES、TDEA、Blowfish、RC2、RC4、RC5、IDEA、SKIPJACK |
||||||
|
AES:高级加密标准(Advanced Encryption Standard) |
||||||
|
DES:数据加密标准(Data Encryption Standard) |
||||||
|
###对称加密第一个案例,代码,。 |
||||||
|
public class SymmetricalEncryptionDemo01 { |
||||||
|
|
||||||
|
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, |
||||||
|
IllegalBlockSizeException, BadPaddingException { |
||||||
|
// 声明要加密的内容 |
||||||
|
String content = "今晚404,不见不散"; |
||||||
|
//生成key |
||||||
|
SecretKey key = createKey(); |
||||||
|
//加密 |
||||||
|
String encryptData = encrypt(content, key); |
||||||
|
System.out.println(encryptData); |
||||||
|
//解密 |
||||||
|
String decryptData = decrypt(encryptData, key); |
||||||
|
System.out.println(decryptData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成key |
||||||
|
* @return |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
*/ |
||||||
|
public static SecretKey createKey() throws NoSuchAlgorithmException { |
||||||
|
// 生成key |
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); |
||||||
|
SecretKey secretKey = keyGenerator.generateKey(); |
||||||
|
return secretKey; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密方法 |
||||||
|
* |
||||||
|
* @param content |
||||||
|
* @return |
||||||
|
* @throws InvalidKeyException |
||||||
|
* @throws NoSuchPaddingException |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
* @throws BadPaddingException |
||||||
|
* @throws IllegalBlockSizeException |
||||||
|
*/ |
||||||
|
public static String encrypt(String content, SecretKey key) throws InvalidKeyException, NoSuchAlgorithmException, |
||||||
|
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { |
||||||
|
// 获取cipher单例对象 |
||||||
|
Cipher cipher = Cipher.getInstance("AES"); |
||||||
|
// 初始化cipher,设置为加密模式 |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, key); |
||||||
|
// 开始加密 |
||||||
|
byte[] encryptBytes = cipher.doFinal(content.getBytes()); |
||||||
|
return Base64.getEncoder().encodeToString(encryptBytes); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param encryptData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String decrypt(String encryptData, SecretKey key) throws InvalidKeyException, |
||||||
|
NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { |
||||||
|
byte[] encryptBytes = Base64.getDecoder().decode(encryptData); |
||||||
|
// 获取cipher单例对象 |
||||||
|
Cipher cipher = Cipher.getInstance("AES"); |
||||||
|
// 解密 |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, key); |
||||||
|
byte[] decryptBytes = cipher.doFinal(encryptBytes); |
||||||
|
return new String(decryptBytes); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
###对称加密的第二个案例,将生成的key保存到本地,然后解密时和下一次加密时就只需要到本地读取即可。。 |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Camille |
||||||
|
*保存key到本地 |
||||||
|
*/ |
||||||
|
public class SymmetricalEncryptionDemo02 { |
||||||
|
|
||||||
|
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, |
||||||
|
IllegalBlockSizeException, BadPaddingException, IOException, ClassNotFoundException { |
||||||
|
// 声明要加密的内容 |
||||||
|
String content = "今晚404,不见不散"; |
||||||
|
//第一次生成key,并序列化到本地 |
||||||
|
// SecretKey key = createKey(); |
||||||
|
// SerializableUtil.saveObject2File("heima.key", key); |
||||||
|
//从文件中读取key |
||||||
|
SecretKey key = (SecretKey) SerializableUtil.readObjectFromFile("heima.key"); |
||||||
|
System.out.println(key); |
||||||
|
//加密 |
||||||
|
String encryptData = encrypt(content, key); |
||||||
|
System.out.println(encryptData); |
||||||
|
//解密 |
||||||
|
String decryptData = decrypt(encryptData, key); |
||||||
|
System.out.println(decryptData); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成key |
||||||
|
* @return |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
*/ |
||||||
|
public static SecretKey createKey() throws NoSuchAlgorithmException { |
||||||
|
// 生成key |
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); |
||||||
|
SecretKey secretKey = keyGenerator.generateKey(); |
||||||
|
return secretKey; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 加密方法 |
||||||
|
* |
||||||
|
* @param content |
||||||
|
* @return |
||||||
|
* @throws InvalidKeyException |
||||||
|
* @throws NoSuchPaddingException |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
* @throws BadPaddingException |
||||||
|
* @throws IllegalBlockSizeException |
||||||
|
*/ |
||||||
|
public static String encrypt(String content, SecretKey key) throws InvalidKeyException, NoSuchAlgorithmException, |
||||||
|
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { |
||||||
|
// 获取cipher单例对象 |
||||||
|
Cipher cipher = Cipher.getInstance("AES"); |
||||||
|
// 初始化cipher,设置为加密模式 |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, key); |
||||||
|
// 开始加密 |
||||||
|
byte[] encryptBytes = cipher.doFinal(content.getBytes()); |
||||||
|
return Base64.getEncoder().encodeToString(encryptBytes); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* @param encryptData |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String decrypt(String encryptData, SecretKey key) throws InvalidKeyException, |
||||||
|
NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { |
||||||
|
byte[] encryptBytes = Base64.getDecoder().decode(encryptData); |
||||||
|
// 获取cipher单例对象 |
||||||
|
Cipher cipher = Cipher.getInstance("AES"); |
||||||
|
// 解密 |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, key); |
||||||
|
byte[] decryptBytes = cipher.doFinal(encryptBytes); |
||||||
|
return new String(decryptBytes); |
||||||
|
} |
||||||
|
} |
||||||
|
**保存对象到文件** |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存对象到本地 |
||||||
|
* |
||||||
|
* @param obj |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
public static void saveObject2File(String fileName, Object obj) throws IOException { |
||||||
|
FileOutputStream fos = new FileOutputStream(new File(fileName)); |
||||||
|
ObjectOutputStream oos = new ObjectOutputStream(fos); |
||||||
|
oos.writeObject(obj); |
||||||
|
} |
||||||
|
**从文件中读取对象** |
||||||
|
|
||||||
|
/** |
||||||
|
* 从文件中读取对象 |
||||||
|
* @param fileName |
||||||
|
* @return |
||||||
|
* @throws IOException |
||||||
|
* @throws ClassNotFoundException |
||||||
|
*/ |
||||||
|
public static Object readObjectFromFile(String fileName) throws IOException, ClassNotFoundException { |
||||||
|
FileInputStream fis = new FileInputStream(new File(fileName)); |
||||||
|
ObjectInputStream ois = new ObjectInputStream(fis); |
||||||
|
Object object = ois.readObject(); |
||||||
|
return object; |
||||||
|
} |
||||||
|
###第三个案例——自定义秘钥,代码 |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成key |
||||||
|
* @return |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
*/ |
||||||
|
public static SecretKey createKey(String keyword) throws NoSuchAlgorithmException { |
||||||
|
// 生成key |
||||||
|
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); |
||||||
|
keyGenerator.init(new SecureRandom(keyword.getBytes())); |
||||||
|
SecretKey secretKey = keyGenerator.generateKey(); |
||||||
|
return secretKey; |
||||||
|
} |
||||||
|
|
||||||
|
###应用场景 |
||||||
|
* 登录,post请求{username=lisi,pw=加密} |
||||||
|
|
||||||
|
##非对称加密的案例 |
||||||
|
常见算法:RSA、Elgamal、背包算法、Rabin、D-H、ECC(椭圆曲线加密算法)等 |
||||||
|
应用场景:银行和电商网站,他就采用非对称加密,将公钥给所有人,你们就用这个公钥加密,私钥我自己留着,谁也不知道,所以除了我,谁也解密不了。 |
||||||
|
###第一个案例(数据量不大的情况下可用,加密数据小于117个字节,解密数据小于128个字节) |
||||||
|
public class AysmmetricEncryptionDemo { |
||||||
|
|
||||||
|
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, |
||||||
|
IllegalBlockSizeException, BadPaddingException { |
||||||
|
String content = "今晚小树林,等你哦"; |
||||||
|
//生成密钥对 |
||||||
|
KeyPair keyPair = createKeyypair(); |
||||||
|
//获取公钥私钥 |
||||||
|
PublicKey publicKey = keyPair.getPublic(); |
||||||
|
PrivateKey privateKey = keyPair.getPrivate(); |
||||||
|
//加密 |
||||||
|
String encryptData = encrypt(content, publicKey); |
||||||
|
System.out.println("加密后:" + encryptData); |
||||||
|
//解密 |
||||||
|
String decryptData = decrypt(encryptData, privateKey); |
||||||
|
System.out.println("解密后:" + decryptData); |
||||||
|
} |
||||||
|
/** |
||||||
|
* 生成秘钥对 |
||||||
|
* @return |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
*/ |
||||||
|
public static KeyPair createKeyypair() throws NoSuchAlgorithmException{ |
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); |
||||||
|
KeyPair keyPair = keyPairGenerator.generateKeyPair(); |
||||||
|
return keyPair; |
||||||
|
} |
||||||
|
/** |
||||||
|
* 加密 |
||||||
|
* |
||||||
|
* @param content |
||||||
|
* @return |
||||||
|
* @throws NoSuchPaddingException |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
* @throws BadPaddingException |
||||||
|
* @throws IllegalBlockSizeException |
||||||
|
* @throws InvalidKeyException |
||||||
|
*/ |
||||||
|
public static String encrypt(String content, PublicKey publicKey) throws NoSuchAlgorithmException, |
||||||
|
NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException { |
||||||
|
// 获取cipher对象 |
||||||
|
Cipher cipher = Cipher.getInstance("RSA"); |
||||||
|
// 初始化cipher,指定模式为加密,传入公钥 |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey); |
||||||
|
byte[] encryptBytes = cipher.doFinal(content.getBytes()); |
||||||
|
return Base64.getEncoder().encodeToString(encryptBytes); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 解密方法 |
||||||
|
* |
||||||
|
* @param encryptData |
||||||
|
* @param privateKey |
||||||
|
* @return |
||||||
|
* @throws NoSuchPaddingException |
||||||
|
* @throws NoSuchAlgorithmException |
||||||
|
* @throws InvalidKeyException |
||||||
|
* @throws BadPaddingException |
||||||
|
* @throws IllegalBlockSizeException |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static String decrypt(String encryptData, PrivateKey privateKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ |
||||||
|
byte[] encryptBytes = Base64.getDecoder().decode(encryptData); |
||||||
|
// 获取cipher对象 |
||||||
|
Cipher cipher = Cipher.getInstance("RSA"); |
||||||
|
// 小芝解密 |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey); |
||||||
|
byte[] decryptBytes = cipher.doFinal(encryptBytes); |
||||||
|
return new String(decryptBytes); |
||||||
|
} |
||||||
|
} |
||||||
|
###如果数据量大的话,则要对要加密、解密的数据进行分块处理,代码如下: |
||||||
|
|
||||||
|
/** |
||||||
|
* 处理大量数据时,分块加密/解密 |
||||||
|
* @param content |
||||||
|
* @param cipher |
||||||
|
* @param max |
||||||
|
* @return |
||||||
|
* @throws IllegalBlockSizeException |
||||||
|
* @throws BadPaddingException |
||||||
|
* @throws IOException |
||||||
|
*/ |
||||||
|
private static byte[] doFinalWithBlock(byte[] bytes, Cipher cipher,int max) |
||||||
|
throws IllegalBlockSizeException, BadPaddingException, IOException { |
||||||
|
int len = bytes.length;//3000 |
||||||
|
//加密数据长度不能超过117个byte |
||||||
|
int inputOffset = 0;//2700 |
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
||||||
|
while (len > inputOffset) { |
||||||
|
//特殊情况,最后一次剩下的数据不足117 |
||||||
|
if ((len - inputOffset) >= max) { |
||||||
|
byte[] encryptBytes = cipher.doFinal(bytes, inputOffset, max); |
||||||
|
baos.write(encryptBytes); |
||||||
|
inputOffset += max; |
||||||
|
}else { |
||||||
|
byte[] encryptBytes = cipher.doFinal(bytes, inputOffset, len - inputOffset); |
||||||
|
baos.write(encryptBytes); |
||||||
|
inputOffset = len; |
||||||
|
} |
||||||
|
} |
||||||
|
byte[] byteArray = baos.toByteArray(); |
||||||
|
return byteArray; |
||||||
|
} |
||||||
|
|
||||||
|
##消息摘要 |
||||||
|
消息摘要是一个不可逆的过程。常用来防篡改。 |
||||||
|
|
||||||
|
常见算法:MD5、SHA、CRC等 |
||||||
|
|
||||||
|
###byte数组和16进制字符串的互转 |
||||||
|
|
||||||
|
/** |
||||||
|
* byte数组转16进制字符串 |
||||||
|
* @param bytes |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String bytes2Hex(byte[] bytes){ |
||||||
|
StringBuffer sBuffer = new StringBuffer(); |
||||||
|
for (int i = 0; i < bytes.length; i++) { |
||||||
|
//取高位 |
||||||
|
int high = (bytes[i] & 0xf0) >> 4; |
||||||
|
//取低位 |
||||||
|
int low = bytes[i] & 0x0f; |
||||||
|
sBuffer.append(HEXSTR[high]).append(HEXSTR[low]); |
||||||
|
} |
||||||
|
return sBuffer.toString(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 16进制字符串转字节数组 |
||||||
|
* @param hex |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static byte[] hex2Bytes(String hex){ |
||||||
|
int len = hex.length()/2; |
||||||
|
//声明一个字节数组用于接收转换后的字节 |
||||||
|
byte[] bytes = new byte[len]; |
||||||
|
for (int i = 0; i < len; i++) { |
||||||
|
//首先取高位,取偶数位 |
||||||
|
String highStr = hex.substring(2 * i, 2 * i + 1); |
||||||
|
String lowStr = hex.substring(2 * i + 1, 2 * i + 2); |
||||||
|
int high = Integer.parseInt(highStr, 16) << 4; |
||||||
|
int low = Integer.parseInt(lowStr, 16); |
||||||
|
bytes[i] = (byte) (high + low); |
||||||
|
} |
||||||
|
return bytes; |
||||||
|
} |
||||||
|
|
||||||
|
##数字签名 |
||||||
|
|
||||||
|
**签名过程** |
||||||
|
|
||||||
|
String content = "404房卡"; |
||||||
|
Signature signature = Signature.getInstance("MD5withRSA"); |
||||||
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); |
||||||
|
KeyPair keyPair = keyPairGenerator.generateKeyPair(); |
||||||
|
PrivateKey privateKey = keyPair.getPrivate(); |
||||||
|
PublicKey publicKey = keyPair.getPublic(); |
||||||
|
signature.initSign(privateKey); |
||||||
|
signature.update(content.getBytes()); |
||||||
|
byte[] sign = signature.sign(); |
||||||
|
|
||||||
|
###数字签名的流程(画图理解) |
||||||
|
###Signature** |
||||||
|
|
||||||
|
//小芝认证 |
||||||
|
signature.initVerify(publicKey); |
||||||
|
//我们要对房卡进行认证 |
||||||
|
// String content2 = "505的房卡"; |
||||||
|
signature.update(content.getBytes()); |
||||||
|
boolean verify = signature.verify(sign); |
||||||
|
Util.printBytes(sign); |
||||||
|
System.out.println(verify); |
||||||
|
##keytool的使用。 |
||||||
|
* 生成keyPair keytool -genkeypair |
||||||
|
* 修改别名 keytool -changealias -alias mykey -destalias heima1 |
||||||
|
* 导出证书 keytool -exportcert |
||||||
|
* 导入证书 keytool -importcert |
||||||
|
|
||||||
|
**获取文件中的证书** |
||||||
|
|
||||||
|
// 获取证书工厂的实例 |
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
||||||
|
FileInputStream inStream = new FileInputStream(new File("heima.cer")); |
||||||
|
X509Certificate certificate = (X509Certificate) cf.generateCertificate(inStream); |
||||||
|
|
||||||
|
##SSl |
||||||
|
**双向认证的原理** |
||||||
|
**代码访问12306** |
||||||
|
|
||||||
|
public class HttpsDemo { |
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, KeyManagementException, KeyStoreException, CertificateException { |
||||||
|
//第一种方式,我所有的证书都不检查 |
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");//TLS 是transport Layer safe |
||||||
|
//获取信任管理者工厂 |
||||||
|
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
||||||
|
//获取keyStore |
||||||
|
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); |
||||||
|
ks.load(null); |
||||||
|
//从文件中读取证书 |
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509"); |
||||||
|
FileInputStream inStream = new FileInputStream(new File("srca.cer")); |
||||||
|
X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream); |
||||||
|
//给keyStore设置证书 |
||||||
|
ks.setCertificateEntry("12306", cert); |
||||||
|
trustManagerFactory.init(ks); |
||||||
|
TrustManager[] tm = trustManagerFactory.getTrustManagers(); |
||||||
|
sslContext.init(null, tm, null); |
||||||
|
SSLSocketFactory socketFactory = sslContext.getSocketFactory(); |
||||||
|
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory); |
||||||
|
// TODO Auto-generated method stub |
||||||
|
URL url = new URL("https://kyfw.12306.cn/otn/"); |
||||||
|
//第二步,获取coon |
||||||
|
HttpsURLConnection coon = (HttpsURLConnection) url.openConnection(); |
||||||
|
InputStream inputStream = coon.getInputStream(); |
||||||
|
String response = Util.inputStream2String(inputStream); |
||||||
|
System.out.println(response); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue