本文主要對消息摘要算法和加密算法作了整理,包括MD五、SHA、DES、AES、RSA等,而且提供了相應算法的Java實現和測試。java
消息摘要算法最經常使用的場景就是數字簽名以及數據(密碼)加密了。(通常平時作項目用的比較多的就是使用MD5對用戶密碼進行加密)git
數字簽名主要用到了非對稱密鑰加密技術與數字摘要技術。數字簽名技術是將摘要信息用發送者的私鑰加密,與原文一塊兒傳送給接收者。接收者只有用發送者的公鑰才能解密被加密的摘要信息,而後用HASH函數對收到的原文產生一個摘要信息,與解密的摘要信息對比。 若是相同,則說明收到的信息是完整的,在傳輸過程當中沒有被修改,不然說明信息被修改過.面試
所以數字簽名可以驗證信息的完整性。 數字簽名是個加密的過程,數字簽名驗證是個解密的過程。算法
MD5的做用是讓大容量信息在用數字簽名軟件簽署私人密鑰前被"壓縮"成一種保密的格式 (也就是把一個任意長度的字節串變換成必定長的十六進制數字串)。apache
利用JDK提供java.security.MessageDigest類實現MD5算法:數組
package com.snailclimb.ks.securityAlgorithm;
import java.security.MessageDigest;
public class MD5Demo {
// test
public static void main(String[] args) {
System.out.println(getMD5Code("你若安好,即是晴天"));
}
private MD5Demo() {
}
// md5加密
public static String getMD5Code(String message) {
String md5Str = "";
try {
//建立MD5算法消息摘要
MessageDigest md = MessageDigest.getInstance("MD5");
//生成的哈希值的字節數組
byte[] md5Bytes = md.digest(message.getBytes());
md5Str = bytes2Hex(md5Bytes);
}catch(Exception e) {
e.printStackTrace();
}
return md5Str;
}
// 2進制轉16進制
public static String bytes2Hex(byte[] bytes) {
StringBuffer result = new StringBuffer();
int temp;
try {
for (int i = 0; i < bytes.length; i++) {
temp = bytes[i];
if(temp < 0) {
temp += 256;
}
if (temp < 16) {
result.append("0");
}
result.append(Integer.toHexString(temp));
}
} catch (Exception e) {
e.printStackTrace();
}
return result.toString();
}
}
複製代碼
結果:安全
6bab82679914f7cb480a120b532ffa80
複製代碼
注意MessageDigest類的幾個方法:bash
static MessageDigest getInstance(String algorithm)//返回實現指定摘要算法的MessageDigest對象 複製代碼
byte[] digest(byte[] input)//使用指定的字節數組對摘要執行最終更新,而後完成摘要計算。
複製代碼
package com.snailclimb.ks.securityAlgorithm;
public class MD5{
/* *四個連接變量 */
private final int A=0x67452301;
private final int B=0xefcdab89;
private final int C=0x98badcfe;
private final int D=0x10325476;
/* *ABCD的臨時變量 */
private int Atemp,Btemp,Ctemp,Dtemp;
/* *常量ti *公式:floor(abs(sin(i+1))×(2pow32) */
private final int K[]={
0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,
0xf57c0faf,0x4787c62a,0xa8304613,0xfd469501,0x698098d8,
0x8b44f7af,0xffff5bb1,0x895cd7be,0x6b901122,0xfd987193,
0xa679438e,0x49b40821,0xf61e2562,0xc040b340,0x265e5a51,
0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,
0xfcefa3f8,0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,
0x6d9d6122,0xfde5380c,0xa4beea44,0x4bdecfa9,0xf6bb4b60,
0xbebfbc70,0x289b7ec6,0xeaa127fa,0xd4ef3085,0x04881d05,
0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,0xf4292244,
0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,
0x4e0811a1,0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391};
/* *向左位移數,計算方法未知 */
private final int s[]={7,12,17,22,7,12,17,22,7,12,17,22,7,
12,17,22,5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,6,10,
15,21,6,10,15,21,6,10,15,21,6,10,15,21};
/* *初始化函數 */
private void init(){
Atemp=A;
Btemp=B;
Ctemp=C;
Dtemp=D;
}
/* *移動必定位數 */
private int shift(int a,int s){
return(a<<s)|(a>>>(32-s));//右移的時候,高位必定要補零,而不是補充符號位
}
/* *主循環 */
private void MainLoop(int M[]){
int F,g;
int a=Atemp;
int b=Btemp;
int c=Ctemp;
int d=Dtemp;
for(int i = 0; i < 64; i ++){
if(i<16){
F=(b&c)|((~b)&d);
g=i;
}else if(i<32){
F=(d&b)|((~d)&c);
g=(5*i+1)%16;
}else if(i<48){
F=b^c^d;
g=(3*i+5)%16;
}else{
F=c^(b|(~d));
g=(7*i)%16;
}
int tmp=d;
d=c;
c=b;
b=b+shift(a+F+K[i]+M[g],s[i]);
a=tmp;
}
Atemp=a+Atemp;
Btemp=b+Btemp;
Ctemp=c+Ctemp;
Dtemp=d+Dtemp;
}
/* *填充函數 *處理後應知足bits≡448(mod512),字節就是bytes≡56(mode64) *填充方式爲先加一個0,其它位補零 *最後加上64位的原來長度 */
private int[] add(String str){
int num=((str.length()+8)/64)+1;//以512位,64個字節爲一組
int strByte[]=new int[num*16];//64/4=16,因此有16個整數
for(int i=0;i<num*16;i++){//所有初始化0
strByte[i]=0;
}
int i;
for(i=0;i<str.length();i++){
strByte[i>>2]|=str.charAt(i)<<((i%4)*8);//一個整數存儲四個字節,小端序
}
strByte[i>>2]|=0x80<<((i%4)*8);//尾部添加1
/* *添加原長度,長度指位的長度,因此要乘8,而後是小端序,因此放在倒數第二個,這裏長度只用了32位 */
strByte[num*16-2]=str.length()*8;
return strByte;
}
/* *調用函數 */
public String getMD5(String source){
init();
int strByte[]=add(source);
for(int i=0;i<strByte.length/16;i++){
int num[]=new int[16];
for(int j=0;j<16;j++){
num[j]=strByte[i*16+j];
}
MainLoop(num);
}
return changeHex(Atemp)+changeHex(Btemp)+changeHex(Ctemp)+changeHex(Dtemp);
}
/* *整數變成16進制字符串 */
private String changeHex(int a){
String str="";
for(int i=0;i<4;i++){
str+=String.format("%2s", Integer.toHexString(((a>>i*8)%(1<<8))&0xff)).replace(' ', '0');
}
return str;
}
/* *單例 */
private static MD5 instance;
public static MD5 getInstance(){
if(instance==null){
instance=new MD5();
}
return instance;
}
private MD5(){};
public static void main(String[] args){
String str=MD5.getInstance().getMD5("你若安好,即是晴天");
System.out.println(str);
}
}
複製代碼
對於長度小於2^64位的消息,SHA1會產生一個160位(40個字符)的消息摘要。當接收到消息的時候,這個消息摘要能夠用來驗證數據的完整性。在傳輸的過程當中,數據極可能會發生變化,那麼這時候就會產生不一樣的消息摘要。微信
SHA1有以下特性:網絡
*利用JDK提供java.security.MessageDigest類實現SHA1算法:
package com.snailclimb.ks.securityAlgorithm;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class SHA1Demo {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(getSha1("你若安好,即是晴天"));
}
public static String getSha1(String str) {
if (null == str || 0 == str.length()) {
return null;
}
char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
//建立SHA1算法消息摘要對象
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
//使用指定的字節數組更新摘要。
mdTemp.update(str.getBytes("UTF-8"));
//生成的哈希值的字節數組
byte[] md = mdTemp.digest();
//SHA1算法生成信息摘要關鍵過程
int j = md.length;
char[] buf = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
buf[k++] = hexDigits[byte0 & 0xf];
}
return new String(buf);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "0";
}
}
複製代碼
結果:
8ce764110a42da9b08504b20e26b19c9e3382414
複製代碼
密鑰加密技術的密碼體制分爲對稱密鑰體制和非對稱密鑰體制兩種。相應地,對數據加密的技術分爲兩類,即對稱加密(私人密鑰加密)和非對稱加密(公開密鑰加密)。
對稱加密以數據加密標準(DES,Data Encryption Standard)算法爲典型表明,非對稱加密一般以RSA(Rivest Shamir Adleman)算法爲表明。
對稱加密的加密密鑰和解密密鑰相同。非對稱加密的加密密鑰和解密密鑰不一樣,加密密鑰能夠公開而解密密鑰須要保密
常被用在電子商務或者其餘須要保證網絡傳輸安全的範圍。
加密密鑰和解密密鑰相同的加密算法。
對稱加密算法使用起來簡單快捷,密鑰較短,且破譯困難,除了數據加密標準(DES), 另外一個對稱密鑰加密系統是國際數據加密算法(IDEA),它比DES的加密性好,並且對計算機功能要求也沒有那麼高。IDEA加密標準由PGP(Pretty Good Privacy)系統使用。
DES全稱爲Data Encryption Standard,即數據加密標準,是一種使用密鑰加密的塊算法,如今已通過時。
DES算法實現 :
package com.snailclimb.ks.securityAlgorithm;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
import javax.crypto.Cipher;
/** * DES加密介紹 DES是一種對稱加密算法,所謂對稱加密算法即:加密和解密使用相同密鑰的算法。DES加密算法出自IBM的研究, * 後來被美國政府正式採用,以後開始普遍流傳,可是近些年使用愈來愈少,由於DES使用56位密鑰,以現代計算能力, * 24小時內便可被破解。雖然如此,在某些簡單應用中,咱們仍是可使用DES加密算法,本文簡單講解DES的JAVA實現 。 * 注意:DES加密和解密過程當中,密鑰長度都必須是8的倍數 */
public class DesDemo {
public DesDemo() {
}
// 測試
public static void main(String args[]) {
// 待加密內容
String str = "cryptology";
// 密碼,長度要是8的倍數
String password = "95880288";
byte[] result;
try {
result = DesDemo.encrypt(str.getBytes(), password);
System.out.println("加密後:" + result);
byte[] decryResult = DesDemo.decrypt(result, password);
System.out.println("解密後:" + new String(decryResult));
} catch (UnsupportedEncodingException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
// 直接將如上內容解密
/** * 加密 * * @param datasource * byte[] * @param password * String * @return byte[] */
public static byte[] encrypt(byte[] datasource, String password) {
try {
SecureRandom random = new SecureRandom();
DESKeySpec desKey = new DESKeySpec(password.getBytes());
// 建立一個密匙工廠,而後用它把DESKeySpec轉換成
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(desKey);
// Cipher對象實際完成加密操做
Cipher cipher = Cipher.getInstance("DES");
// 用密匙初始化Cipher對象,ENCRYPT_MODE用於將 Cipher 初始化爲加密模式的常量
cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
// 如今,獲取數據並加密
// 正式執行加密操做
return cipher.doFinal(datasource); // 按單部分操做加密或解密數據,或者結束一個多部分操做
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
/** * 解密 * * @param src * byte[] * @param password * String * @return byte[] * @throws Exception */
public static byte[] decrypt(byte[] src, String password) throws Exception {
// DES算法要求有一個可信任的隨機數源
SecureRandom random = new SecureRandom();
// 建立一個DESKeySpec對象
DESKeySpec desKey = new DESKeySpec(password.getBytes());
// 建立一個密匙工廠
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");// 返回實現指定轉換的
// Cipher
// 對象
// 將DESKeySpec對象轉換成SecretKey對象
SecretKey securekey = keyFactory.generateSecret(desKey);
// Cipher對象實際完成解密操做
Cipher cipher = Cipher.getInstance("DES");
// 用密匙初始化Cipher對象
cipher.init(Cipher.DECRYPT_MODE, securekey, random);
// 真正開始解密操做
return cipher.doFinal(src);
}
}
複製代碼
結果:
加密後:[B@50cbc42f
解密後:cryptology
複製代碼
IDEA算法實現
package com.snailclimb.ks.securityAlgorithm;
import java.security.Key;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
public class IDEADemo {
public static void main(String args[]) {
bcIDEA();
}
public static void bcIDEA() {
String src = "www.xttblog.com security idea";
try {
Security.addProvider(new BouncyCastleProvider());
//生成key
KeyGenerator keyGenerator = KeyGenerator.getInstance("IDEA");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] keyBytes = secretKey.getEncoded();
//轉換密鑰
Key key = new SecretKeySpec(keyBytes, "IDEA");
//加密
Cipher cipher = Cipher.getInstance("IDEA/ECB/ISO10126Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(src.getBytes());
System.out.println("bc idea encrypt : " + Base64.encodeBase64String(result));
//解密
cipher.init(Cipher.DECRYPT_MODE, key);
result = cipher.doFinal(result);
System.out.println("bc idea decrypt : " + new String(result));
} catch (Exception e) {
e.printStackTrace();
}
}
}
複製代碼
RSA是目前最有影響力和最經常使用的公鑰加密算法。它可以抵抗到目前爲止已知的絕大多數密碼攻擊,已被ISO推薦爲公鑰數據加密標準。
RAS算法實現:
package com.snailclimb.ks.securityAlgorithm;
import org.apache.commons.codec.binary.Base64;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
/** * Created by humf.須要依賴 commons-codec 包 */
public class RSADemo {
public static void main(String[] args) throws Exception {
Map<String, Key> keyMap = initKey();
String publicKey = getPublicKey(keyMap);
String privateKey = getPrivateKey(keyMap);
System.out.println(keyMap);
System.out.println("-----------------------------------");
System.out.println(publicKey);
System.out.println("-----------------------------------");
System.out.println(privateKey);
System.out.println("-----------------------------------");
byte[] encryptByPrivateKey = encryptByPrivateKey("123456".getBytes(), privateKey);
byte[] encryptByPublicKey = encryptByPublicKey("123456", publicKey);
System.out.println(encryptByPrivateKey);
System.out.println("-----------------------------------");
System.out.println(encryptByPublicKey);
System.out.println("-----------------------------------");
String sign = sign(encryptByPrivateKey, privateKey);
System.out.println(sign);
System.out.println("-----------------------------------");
boolean verify = verify(encryptByPrivateKey, publicKey, sign);
System.out.println(verify);
System.out.println("-----------------------------------");
byte[] decryptByPublicKey = decryptByPublicKey(encryptByPrivateKey, publicKey);
byte[] decryptByPrivateKey = decryptByPrivateKey(encryptByPublicKey, privateKey);
System.out.println(decryptByPublicKey);
System.out.println("-----------------------------------");
System.out.println(decryptByPrivateKey);
}
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
public static byte[] decryptBASE64(String key) {
return Base64.decodeBase64(key);
}
public static String encryptBASE64(byte[] bytes) {
return Base64.encodeBase64String(bytes);
}
/** * 用私鑰對信息生成數字簽名 * * @param data * 加密數據 * @param privateKey * 私鑰 * @return * @throws Exception */
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64編碼的私鑰
byte[] keyBytes = decryptBASE64(privateKey);
// 構造PKCS8EncodedKeySpec對象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私鑰匙對象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私鑰對信息生成數字簽名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/** * 校驗數字簽名 * * @param data * 加密數據 * @param publicKey * 公鑰 * @param sign * 數字簽名 * @return 校驗成功返回true 失敗返回false * @throws Exception */
public static boolean verify(byte[] data, String publicKey, String sign) throws Exception {
// 解密由base64編碼的公鑰
byte[] keyBytes = decryptBASE64(publicKey);
// 構造X509EncodedKeySpec對象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公鑰匙對象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 驗證簽名是否正常
return signature.verify(decryptBASE64(sign));
}
public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得私鑰
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 對數據解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/** * 解密<br> * 用私鑰解密 * * @param data * @param key * @return * @throws Exception */
public static byte[] decryptByPrivateKey(String data, String key) throws Exception {
return decryptByPrivateKey(decryptBASE64(data), key);
}
/** * 解密<br> * 用公鑰解密 * * @param data * @param key * @return * @throws Exception */
public static byte[] decryptByPublicKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得公鑰
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 對數據解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/** * 加密<br> * 用公鑰加密 * * @param data * @param key * @return * @throws Exception */
public static byte[] encryptByPublicKey(String data, String key) throws Exception {
// 對公鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得公鑰
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 對數據加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data.getBytes());
}
/** * 加密<br> * 用私鑰加密 * * @param data * @param key * @return * @throws Exception */
public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {
// 對密鑰解密
byte[] keyBytes = decryptBASE64(key);
// 取得私鑰
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 對數據加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/** * 取得私鑰 * * @param keyMap * @return * @throws Exception */
public static String getPrivateKey(Map<String, Key> keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/** * 取得公鑰 * * @param keyMap * @return * @throws Exception */
public static String getPublicKey(Map<String, Key> keyMap) throws Exception {
Key key = keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/** * 初始化密鑰 * * @return * @throws Exception */
public static Map<String, Key> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
Map<String, Key> keyMap = new HashMap(2);
keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公鑰
keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私鑰
return keyMap;
}
}
複製代碼
結果:
{RSAPublicKey=Sun RSA public key, 1024 bits
modulus: 115328826086047873902606456571034976538836553998745367981848911677968062571831626674499650854318207280419960767020601253071739555161388135589487284843845439403614883967713749605268831336418001722701924537624573180276356615050309809260289965219855862692230362893996010057188170525719351126759886050891484226169
public exponent: 65537, RSAPrivateKey=sun.security.rsa.RSAPrivateCrtKeyImpl@93479}
-----------------------------------
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCkO9PBTOFJQTkzznALN62PU7ixd9YFjXrt2dPOGj3wwhymbOU8HLoCztjwpLXHgbpBUJlGmbURV955M1BkZ1kr5dkZYR5x1gO4xOnu8rEipy4AAMcpFttfiarIZrtzL9pKEvEOxABltVN4yzFDr3IjBqY46aHna7YjwhXI0xHieQIDAQAB
-----------------------------------
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKQ708FM4UlBOTPOcAs3rY9TuLF31gWNeu3Z084aPfDCHKZs5TwcugLO2PCktceBukFQmUaZtRFX3nkzUGRnWSvl2RlhHnHWA7jE6e7ysSKnLgAAxykW21+Jqshmu3Mv2koS8Q7EAGW1U3jLMUOvciMGpjjpoedrtiPCFcjTEeJ5AgMBAAECgYAK4sxOa8IjEOexv2U92Rrv/SSo3sCY7Z/QVDft2V9xrewoO9+V9HF/7iYDDWffKYInAiimvVl7JM/iSLxza0ZFv29VMpyDcr4TigYmWwBlk7ZbxSTkqLdNwxxldMmEoTn1py53MUm+1V1K3rzNvJjuZaZFAevU7vUnwQwD+JGQYQJBAM9HBaC+dF3PJ2mkXekHpDS1ZPaSFdrdzd/GvHFi/cJAMM+Uz6PmpkosNXRtOpSYWwlOMRamLZtrHhfQoqSk3S8CQQDK1qL1jGvVdqw5OjqxktR7MmOsWUVZdWiBN+6ojxBgA0yVn0n7vkdAAgEZBj89WG0VHPEu3hd4AgXFZHDfXeDXAkBvSn7nE9t/Et7ihfI2UHgGJO8UxNMfNMB5Skebyb7eMYEDs67ZHdpjMOFypcMyTatzj5wjwQ3zyMvblZX+ONbZAkAX4ysRy9WvL+icXLUo0Gfhkk+WrnSyUldaUGH0y9Rb2kecn0OxN/lgGlxSvB+ac910zRHCOTl+Uo6nbmq0g3PFAkAyqA4eT7G9GXfncakgW1Kdkn72w/ODpozgfhTLNX0SGw1ITML3c4THTtH5h3zLi3AF9zJO2O+K6ajRbV0szHHI
-----------------------------------
[B@387c703b
-----------------------------------
[B@224aed64
-----------------------------------
la4Hc4n/UbeBu0z9iLRuwKVv014SiOJMXkO5qdJvKBsw0MlnsrM+89a3p73yMrb1dAnCU/2kgO0PtFpvmG8pzxTe1u/5nX/25iIyUXALlwVRptJyjzFE83g2IX0XEv/Dxqr1RCRcrMHOLQM0oBoxZCaChmyw1Ub4wsSs6Ndxb9M=
-----------------------------------
true
-----------------------------------
[B@c39f790
-----------------------------------
[B@71e7a66b
複製代碼
若是想要獲取更多個人原創文章,歡迎關注個人微信公衆號:"Java面試通關手冊" 。無套路,但願能與您共同進步,互相學習。