一、消息摘要
消息摘要是一種與消息認證結合使用以確保消息完整性的技術,消息摘要採用單向Hash函數將加密的明文“摘要”成一串密文,則這串密文亦稱爲數字指紋(Finger Print),則接受者通過對接受到信息的新產生的摘要與原摘要比較,就知道消息是否被修改了
特點:
- 唯一性
- 不可逆
- 不需要祕鑰
- 長度固定,無論輸入的明文有多長,計算出的消息摘要的長度總數固定的
原理:消息摘要就是將需要摘要的數據作爲參數,經過Hash函數計算,得到的散列值
常用消息摘要算法:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm, 安全散列算法)、MAC(Message AuthenticationCode,消息認證碼算法),目前廣泛使用算法MD5、SHA1
@Test
public void testMD() throws Exception {
String plainText = "USE MD";
System.out.println("明文:" + plainText);
// 使用getInstance("算法")來獲得消息摘要
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
// 開始使用算法
messageDigest.update(plainText.getBytes());
// 得到摘要
byte[] digestByte = messageDigest.digest();
// 摘要長度始終爲16個字節,128位
System.out.println("摘要長度:" + digestByte.length);
// 輸出算法運算結果,防止亂碼,使用Base64編碼
String encode = Base64.encodeBase64String(digestByte);
System.out.println("摘要:" + encode);
}
結果:
二、對稱加密
消息發送方和消息接收方必須使用相同的密鑰
對稱加密常用算法:DES(Data Encryption Standard, 數據加密標準)、AES(Advanced Encryption Standard, 高級加密標準)
@Test
public void testAES() throws Exception {
String plainText = "USE AES";
System.out.println("明文:" + plainText);
// 得到一個使用AES算法的KeyGenerator的實例
KeyGenerator kenGen = KeyGenerator.getInstance("AES");
// 定義祕鑰長度128位
kenGen.init(128);
// 通過KeyGenerator產生一個key(祕鑰算法剛纔已定義,爲AES)
Key key = kenGen.generateKey();
// 1.獲取加密工具類,定義Cipher的基本信息,ECB是加密方法,PKCS5Padding是填充方法
// 算法/工作模式/填充模式(algorithm/mode/padding
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
// 2.加密,對工具類對象進行初始化
cipher.init(Cipher.ENCRYPT_MODE, key);
// 3.用加密工具類對象對明文進行加密
byte[] encipherByte = cipher.doFinal(plainText.getBytes());
String encode = Base64.encodeBase64String(encipherByte);
System.out.println("加密:" + encode);
// 2.解密
cipher.init(Cipher.DECRYPT_MODE, key);
// 3.用加密工具類對象對密文進行解密
byte[] decode = Base64.decodeBase64(encode);
byte[] decipherByte = cipher.doFinal(decode);
String decipherText = new String(decipherByte);
System.out.println("解密:" + decipherText);
}
結果:
三、非對稱加密
非對稱加密算法需要兩個密鑰:公開密鑰(publickey)和私有密鑰(privatekey)
非對稱加密常用算法:RSA
@Test
public void testRSA() throws Exception {
String plainText = "USE RSA";
System.out.println("明文:" + plainText);
// 產生一個RSA祕鑰生成器KeyPairGenerator(一對鑰匙生成器)
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
// 定義祕鑰長度512位
keyGen.initialize(512);
// 通過KeyPairGenerator產生祕鑰,注意這裏的key是一對鑰匙
KeyPair key = keyGen.generateKeyPair();
// 1.獲取加密工具類
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
// 2.使用公鑰加密,對工具類對象進行初始化
cipher.init(Cipher.ENCRYPT_MODE, key.getPublic());
// 3.用加密工具類對象對明文進行加密
byte[] encipherByte = cipher.doFinal(plainText.getBytes());
String encode = Base64.encodeBase64String(encipherByte);
System.out.println("加密:" + encode);
// 2.使用私鑰解密,對工具類對象進行初始化
// PrivateKey privateKey = KeyFactory.getInstance("RSA")
// .generatePrivate(new PKCS8EncodedKeySpec(key.getPrivate().getEncoded()));
// cipher.init(Cipher.DECRYPT_MODE, privateKey);
cipher.init(Cipher.DECRYPT_MODE, key.getPrivate());
// 3.用加密工具類對象對密文進行解密
byte[] decode = Base64.decodeBase64(encode);
byte[] decipherByte = cipher.doFinal(decode);
String decipherText = new String(decipherByte);
System.out.println("解密:" + decipherText);
}
結果:
四、數字簽名
數字簽名的主要作用就是保證了數據的有效性(驗證是誰發的)和完整性(證明信息沒有被篡改)
摘要經過加密,就得到數字簽名
簽名算法有:MD5withRSA、SHA1withRSA、SHA256withRSA
@Test
public void testSign() throws Exception {
String plainText = "USE RSA TO SIGNATURE";
System.out.println("正文:" + plainText);
// 形成RSA公鑰對
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(512);
KeyPair key = keyGen.generateKeyPair();
// 1.獲取簽名工具類
Signature sig = Signature.getInstance("MD5withRSA");
// 2.初始化簽名,使用私鑰簽名
sig.initSign(key.getPrivate());
sig.update(plainText.getBytes());
// 3.得到簽名
byte[] signByte = sig.sign();
String encode = Base64.encodeBase64String(signByte);
System.out.println("簽名:" + encode);
// 2.初始化驗證,使用公鑰驗證
sig.initVerify(key.getPublic());
sig.update(plainText.getBytes());
// 3.進行驗證
byte[] decode = Base64.decodeBase64(encode);
if (sig.verify(decode)) {
System.out.println("簽名驗證正確!");
} else {
System.out.println("簽名驗證失敗!");
}
}
結果: