加密算法總結(jié)

對(duì)稱(chēng)與非對(duì)稱(chēng)加密算法的區(qū)別。

對(duì)稱(chēng)加密算法

加密(encryption)與解密(decryption)用的是同樣的密鑰(secret key),這種加密方式加密速度非常快生年,適合經(jīng)常發(fā)送數(shù)據(jù)的場(chǎng)合。缺點(diǎn)是密鑰的傳輸比較麻煩鸟缕。

非對(duì)稱(chēng)加密算法

非對(duì)稱(chēng)加密為數(shù)據(jù)的加密與解密提供了一個(gè)非常安全的方法晶框,它使用了一對(duì)密鑰,公鑰(public key)和私鑰(private key)懂从。私鑰只能由一方安全保管授段,不能外泄,而公鑰則可以發(fā)給任何請(qǐng)求它的人番甩。非對(duì)稱(chēng)加密使用這對(duì)密鑰中的一個(gè)進(jìn)行加密侵贵,而解密則需要另一個(gè)密鑰。比如缘薛,你向銀行請(qǐng)求公鑰窍育,銀行將公鑰發(fā)給你卡睦,你使用公鑰對(duì)消息加密,那么只有私鑰的持有人--銀行才能對(duì)你的消息解密漱抓。與對(duì)稱(chēng)加密不同的是表锻,銀行不需要將私鑰通過(guò)網(wǎng)絡(luò)發(fā)送出去,因此安全性大大提高乞娄。

常見(jiàn)的非對(duì)稱(chēng)加密算法為RSA瞬逊、ECC和EIGamal。

一仪或、Hex編碼與解碼

Hex 全稱(chēng)是Intel HEX确镊。Hex文件是由一行行符合Intel HEX文件格式的文本所構(gòu)成的ASCII文本文件。在Intel HEX文件中范删,每一行包含一個(gè)HEX記錄蕾域。這些記錄由對(duì)應(yīng)機(jī)器語(yǔ)言碼和/或常量數(shù)據(jù)的十六進(jìn)制編碼數(shù)字組成。

如下:

99到旦、105旨巷、224,7

編碼之后的數(shù)據(jù)為:“6369e007”厢绝,是一個(gè)字符串契沫。

pom依賴? ? ?

<dependency>

? <groupId>commons-codec</groupId>

? <artifactId>commons-codec</artifactId>

? <version>1.10</version>

</dependency>

編碼與解碼測(cè)試如下:

/**

? * Hex編碼

*/

public static String encodeHex(byte[] input) {

? ? return Hex.encodeHexString(input);

}

/**

? * Hex解碼

? */

public static byte[] decodeHex(String input) {

? ? try {

? ? ? ? return Hex.decodeHex(input.toCharArray());

? ? } catch (DataBindingException e) {

? ? ? ? throw new RuntimeException();

? ? } catch (DecoderException e) {

? ? ? ? throw new RuntimeException();

? ? }

}

二带猴、Base64編碼與解碼

/**

? * Base64編碼

? */

public static String encodeBase64(byte[] input) {

? ? return Base64.encodeBase64String(input);

}

/**

? * Base64編碼, URL安全(將Base64中的URL非法字符'+'和'/'轉(zhuǎn)為'-'和'_', 見(jiàn)RFC3548)

? */

public static String encodeUrlSafeBase64(byte[] input) {

? ? return Base64.encodeBase64URLSafeString(input);

}

/**

? * Base64解碼.

? */

public static byte[] decodeBase64(String input) {

? ? return Base64.decodeBase64(input);

}

測(cè)試如下:

public class Base64Test {

????public static void main(String[] args){

????????String str = "Hello World";

????????try{

????????????System.out.println("RESULT: " + encodeStr(str));

????????} catch(UnsupportedEncodingException e){

????????????e.printStackTrace();

????????}

????}

}

輸出結(jié)果為:

1.? RESULT: SGVsbG8gV29ybGQ=?

上面輸出的字符串是“Hello world”字符串的8位二進(jìn)制值被連接在一起昔汉,然后以6位分組。隨后每個(gè)組都被轉(zhuǎn)換成一個(gè)單獨(dú)的數(shù)字并映射到Base64的索引拴清。

binary? dec Base64

010010? 18? S

000110? 6? G

010101? 21? V

101100? 44? s

011011? 27? b

000110? 6? G

111100? 60? 8

100000? 32? g

010101? 29? d

110110? 54? 2

111101? 61? 9

110010? 50? y

011011? 27? b

000110? 6? G

010000? 16? Q

注意:字符串最后加上了“=”靶病,其意思表示字符串編碼的結(jié)束。

三口予、URL編碼與解碼

當(dāng)URL地址里包含非西歐字符的字符串時(shí)娄周,瀏覽器都會(huì)將這些非西歐字符串轉(zhuǎn)換成application/x-www-form-urlencoded MIME 字符串。在開(kāi)發(fā)過(guò)程中沪停,我們可能涉及將普通字符串和這種特殊字符串的相關(guān)轉(zhuǎn)換煤辨,這就需要使用 URLDecoder 和 URLEncoder類(lèi)進(jìn)行實(shí)現(xiàn),其中:

·? ? ? URLDecoder類(lèi)包含一個(gè)decode(String s,String enc)靜態(tài)方法木张,它可以將application/x-www-form-urlencoded MIME字符串轉(zhuǎn)成普通字符串众辨;

·? ? ? URLEncoder類(lèi)包含一個(gè)encode(String s,String enc)靜態(tài)方法,它可以將普通字符串轉(zhuǎn)換成application/x-www-form-urlencoded MIME字符串舷礼。

普通字符串轉(zhuǎn)與 application/x-www-form-urlencoded MIME 字符串之間的轉(zhuǎn)化:

public class URLDecoderTest {

? public static void main(String[] args) throws Exception {

? ? // 將application/x-www-form-urlencoded字符串轉(zhuǎn)換成普通字符串

? ? // 其中的字符串直接從上圖所示窗口復(fù)制過(guò)來(lái),chrome 默認(rèn)用 UTF-8 字符集進(jìn)行編碼鹃彻,所以也應(yīng)該用對(duì)應(yīng)的字符集解碼

? ? System.out.println("采用UTF-8字符集進(jìn)行解碼:");

? ? String keyWord = URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "UTF-8");

? ? System.out.println(keyWord);

? ? System.out.println("\n 采用GBK字符集進(jìn)行解碼:");

? ? System.out.println(URLDecoder.decode("%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6+Rico", "GBK"));

? ? // 將普通字符串轉(zhuǎn)換成application/x-www-form-urlencoded字符串

? ? System.out.println("\n 采用utf-8字符集:");

? ? String urlStr = URLEncoder.encode("天津大學(xué)", "utf-8");

? ? System.out.println(urlStr);

? ? System.out.println("\n 采用GBK字符集:");

? ? String urlStr2 = URLEncoder.encode("天津大學(xué)", "GBK");

? ? System.out.println(urlStr2);

? }

}

/*

Output:

采用UTF-8字符集進(jìn)行解碼:

天津大學(xué) Rico

采用GBK字符集進(jìn)行解碼:

澶╂觸澶у Rico

采用utf-8字符集:

%E5%A4%A9%E6%B4%A5%E5%A4%A7%E5%AD%A6

采用GBK字符集:

? ? %CC%EC%BD%F2%B4%F3%D1%A7

*/

四、AES加密或解密

高級(jí)加密標(biāo)準(zhǔn)(AES,Advanced Encryption Standard)為最常見(jiàn)的對(duì)稱(chēng)加密算法妻献。對(duì)稱(chēng)加密算法也就是加密和解密用相同的密鑰

密鑰K:用來(lái)加密明文的密碼蛛株,在對(duì)稱(chēng)加密算法中团赁,加密與解密的密鑰是相同的。密鑰為接收方與發(fā)送方協(xié)商產(chǎn)生谨履,但不可以直接在網(wǎng)絡(luò)上傳輸欢摄,否則會(huì)導(dǎo)致密鑰泄漏,通常是通過(guò)非對(duì)稱(chēng)加密算法加密密鑰笋粟,然后再通過(guò)網(wǎng)絡(luò)傳輸給對(duì)方剧浸,或者直接面對(duì)面商量密鑰。密鑰是絕對(duì)不可以泄漏的矗钟,否則會(huì)被攻擊者還原密文唆香,竊取機(jī)密數(shù)據(jù)。

1吨艇、密鑰

就是把明文轉(zhuǎn)換為密文躬它,密文轉(zhuǎn)換為明文的一把鑰匙。接下來(lái)我們會(huì)用ASE加密技術(shù)生成一把密鑰东涡。

/**

* 生成AES密鑰,可選長(zhǎng)度為128,192,256位.

*/

public static byte[] generateAesKey(int keysize) {

? try {

? ? KeyGenerator keyGenerator = KeyGenerator.getInstance(AES);

? ? keyGenerator.init(keysize);

? ? SecretKey secretKey = keyGenerator.generateKey();

? ? return secretKey.getEncoded();

? } catch (GeneralSecurityException e) {

? ? throw unchecked(e);

? }

}

2冯吓、加密,將明文和密鑰一起疮跑,作為參數(shù)傳入组贺。

/**

* ASE 加密

* @param str 明文

* @param key 秘鑰

* @return

*/

public static String enStr(String str, byte[] key) {

Cipher cipher = null;

SecretKey generateKey = null;

? try {

? ? generateKey = new SecretKeySpec(key, "AES");

? ? cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

? ? cipher.init(Cipher.ENCRYPT_MODE, generateKey);

? ? byte[] resultBytes = cipher.doFinal(str.getBytes());

? ? return Hex.encodeHexString(resultBytes);

? } catch (Exception e) {

? ? logger.error("AES加密出錯(cuò)", e);

? }

? return null;

}

3、解密祖娘,解密就是加密的互逆過(guò)程失尖,所以代碼很類(lèi)似。

/**

* 解密

* @param key 秘鑰

* @param str 密文

* @return

*/

public static String deStr(String str, byte[] key) {

? Cipher cipher = null;

? SecretKey generateKey = null;

? try {

? generateKey = new SecretKeySpec(key, "AES");

? cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");

? cipher.init(Cipher.DECRYPT_MODE, generateKey);

? byte[] result = Hex.decodeHex(str.toCharArray());

? return new String(cipher.doFinal(result));

? } catch(Exception e) {

? ? ? logger.error("ASE解密出錯(cuò)", e);

? }

? return null;

}

通用公共抽冉ニ铡:

/**

* 使用AES加密或解密無(wú)編碼的原始字節(jié)數(shù)組, 返回?zé)o編碼的字節(jié)數(shù)組結(jié)果.

*

* @param input 原始字節(jié)數(shù)組

* @param key 符合AES要求的密鑰

* @param mode Cipher.ENCRYPT_MODE 或 Cipher.DECRYPT_MODE

*/

private static byte[] aes(byte[] input, byte[] key, int mode) {

? ? try {

? ? ? ? SecretKey secretKey = new SecretKeySpec(key, AES);

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

? ? ? ? cipher.init(mode, secretKey);

? ? ? ? return cipher.doFinal(input);

? ? } catch (GeneralSecurityException e) {

? ? ? ? throw unchecked(e);

? ? }

}

五掀潮、DES加密與解密(3DES)

數(shù)據(jù)加密標(biāo)準(zhǔn)(DES Data Encryption Standard)

DES算法的入口參數(shù)有三個(gè):Key、Data琼富、Mode仪吧。

其中Key為8個(gè)字節(jié)共64位,是DES算法的工作密鑰鞠眉;

Data也為8個(gè)字節(jié)64位薯鼠,是要被加密或被解密的數(shù)據(jù);

Mode為DES的工作方式械蹋,有兩種:加密或解密出皇。

DES算法是這樣工作的:

如Mode為加密,則用Key 去把數(shù)據(jù)Data進(jìn)行加密朝蜘,生成Data的密碼形式(64位)作為DES的輸出結(jié)果恶迈;

如Mode為解密,則用Key去把密碼形式的數(shù)據(jù)Data解密,還原為Data的明碼形式(64位)作為DES的輸出結(jié)果暇仲。

3DES加密:

3DES是DES加密算法的一種模式步做,它使用3條64位的密鑰對(duì)數(shù)據(jù)進(jìn)行三次加密。數(shù)據(jù)加密標(biāo)準(zhǔn)(DES)是美國(guó)的一種由來(lái)已久的加密標(biāo)準(zhǔn)奈附,它使用對(duì)稱(chēng)密鑰加密法全度。

3DES(即Triple DES)是DES向AES過(guò)渡的加密算法(1999年,NIST將3-DES指定為過(guò)渡的加密標(biāo)準(zhǔn))斥滤,是DES的一個(gè)更安全的變形将鸵。它以DES為基本模塊,通過(guò)組合分組方法設(shè)計(jì)出分組加密算法佑颇。

設(shè)Ek()和Dk()代表DES算法的加密和解密過(guò)程顶掉,K代表DES算法使用的密鑰,P代表明文挑胸,C代表密表痒筒,這樣,

3DES加密過(guò)程為:C=Ek3(Dk2(Ek1(P)))

3DES解密過(guò)程為:P=Dk1((EK2(Dk3(C)))

K1茬贵、K2簿透、K3決定了算法的安全性,若三個(gè)密鑰互不相同解藻,本質(zhì)上就相當(dāng)于用一個(gè)長(zhǎng)為168位的密鑰進(jìn)行加密老充。多年來(lái),它在對(duì)付強(qiáng)力攻擊時(shí)是比較安全的螟左。若數(shù)據(jù)對(duì)安全性要求不那么高啡浊,K1可以等于K3。在這種情況下路狮,密鑰的有效長(zhǎng)度為112位虫啥。

五蔚约、RSA加密與解密

非對(duì)稱(chēng)加密奄妨,公鑰加密,私鑰解密苹祟,反之亦然砸抛。由于需要大數(shù)的乘冪求模等算法,運(yùn)行速度慢树枫,不易于硬件實(shí)現(xiàn)直焙。

通常私鑰長(zhǎng)度有512bit,1024bit砂轻,2048bit奔誓,4096bit,長(zhǎng)度越長(zhǎng),越安全厨喂,但是生成密鑰越慢和措,加解密也越耗時(shí)。

既然是加密蜕煌,那肯定是不希望別人知道我的消息派阱,所以只有我才能解密,所以可得出公鑰負(fù)責(zé)加密斜纪,私鑰負(fù)責(zé)解密贫母;

同理,既然是簽名盒刚,那肯定是不希望有人冒充我發(fā)消息腺劣,只有我才能發(fā)布這個(gè)簽名,所以可得出私鑰負(fù)責(zé)簽名因块,公鑰負(fù)責(zé)驗(yàn)證誓酒。

六、MD5加密(不可逆)

MD5即Message-Digest Algorithm 5(信息-摘要算法5), 非對(duì)稱(chēng)的加密算法

public static String MD5(String key) {

char hexDigits[] = {

'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'

};

? try {

? ? byte[] btInput = key.getBytes();

? ? // 獲得MD5摘要算法的 MessageDigest 對(duì)象

? ? MessageDigest mdInst = MessageDigest.getInstance("MD5");

? ? // 使用指定的字節(jié)更新摘要

? ? mdInst.update(btInput);

? ? // 獲得密文

? ? byte[] md = mdInst.digest();

? ? // 把密文轉(zhuǎn)換成十六進(jìn)制的字符串形式

? ? int j = md.length;

? ? charstr[] = newchar[j * 2];

? ? int k = 0;

? ? for (int i = 0; i < j; i++) {

? ? ? byte byte0 = md[i];

? ? ? str[k++] = hexDigits[byte0 >>> 4 & 0xf];

? ? ? str[k++] = hexDigits[byte0 & 0xf];

? ? }

? ? return new String(str);

? } catch (Exception e) {

? ? returnnull;

? }

}

總結(jié)

哈希函數(shù),比如MD5,SHA贮聂,這些都不是加密算法靠柑。要注意他們的區(qū)別和用途,很多網(wǎng)友都把md5說(shuō)成是加密算法吓懈,這是嚴(yán)重不正確的啊歼冰。

哈希函數(shù):MD5SHA 是沒(méi)有密鑰的耻警,相當(dāng)與指紋的概念隔嫡,因此也是不可逆的;

md5128位的甘穿,SHA有不同的算法腮恩,有128256等位温兼。秸滴。。如SHA-256,SHA-384

然后就是 Base64,這更加不屬于加密算法的范圍了募判,它只是將byte[]數(shù)組進(jìn)行了轉(zhuǎn)換荡含,為什么要轉(zhuǎn)換呢?就是因?yàn)楹芏嗉用芎蟮拿芪暮笳咭恍┨厥獾?/b>byte[]數(shù)組需要顯示出來(lái)届垫,或者需要進(jìn)行傳遞(電子郵件)释液,但是直接轉(zhuǎn)換就會(huì)導(dǎo)致很多不可顯示的字符,會(huì)丟失一些信息装处,因此就轉(zhuǎn)換位Base64編碼误债,這些都是可顯示的字符。所以轉(zhuǎn)換后,長(zhǎng)度會(huì)增加寝蹈。它是可逆的糟袁。

再就是 3DES,DES 這才是加密算法,因此也是可逆的躺盛,加解密需要密鑰,也就是你說(shuō)的key

最后是 RSA ,這是公鑰密碼项戴,也就是加密和解密密鑰不同,也是可逆的槽惫。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末周叮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子界斜,更是在濱河造成了極大的恐慌仿耽,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件各薇,死亡現(xiàn)場(chǎng)離奇詭異项贺,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)峭判,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)开缎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人林螃,你說(shuō)我怎么就攤上這事奕删。” “怎么了疗认?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵完残,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我横漏,道長(zhǎng)谨设,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任缎浇,我火速辦了婚禮扎拣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘华畏。我一直安慰自己鹏秋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布亡笑。 她就那樣靜靜地躺著,像睡著了一般横朋。 火紅的嫁衣襯著肌膚如雪仑乌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音晰甚,去河邊找鬼衙传。 笑死,一個(gè)胖子當(dāng)著我的面吹牛厕九,可吹牛的內(nèi)容都是我干的蓖捶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼扁远,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼俊鱼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起畅买,我...
    開(kāi)封第一講書(shū)人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤并闲,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后谷羞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體帝火,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年湃缎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了犀填。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嗓违,死狀恐怖宏浩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情靠瞎,我是刑警寧澤比庄,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站乏盐,受9級(jí)特大地震影響佳窑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜父能,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一神凑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧何吝,春花似錦溉委、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至黔酥,卻和暖如春藻三,著一層夾襖步出監(jiān)牢的瞬間洪橘,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工棵帽, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留熄求,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓逗概,卻偏偏與公主長(zhǎng)得像弟晚,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子逾苫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容