[Java 安全]加密算法
Base64編碼
算法簡(jiǎn)述
定義
Base64內(nèi)容傳送編碼是一種以任意8位字節(jié)序列組合的描述形式,這種形式不易被人直接識(shí)別。
Base64是一種很常見的編碼規(guī)范,其作用是將二進(jìn)制序列轉(zhuǎn)換為人類可讀的ASCII字符序列,常用在需用通過文本協(xié)議(比如HTTP和SMTP)來傳輸二進(jìn)制數(shù)據(jù)的情況下。Base64并不是加密解密算法,盡管我們有時(shí)也聽到使用Base64來加密解密的說法,但這里所說的加密與解密實(shí)際是指編碼(encode)和解碼(decode)的過程,其變換是非常簡(jiǎn)單的,僅僅能夠避免信息被直接識(shí)別。
?
原理
Base64算法主要是將給定的字符以字符編碼(如ASCII碼,UTF-8碼)對(duì)應(yīng)的十進(jìn)制數(shù)為基準(zhǔn),做編碼操作:
(1)將給定的字符串以字符為單位,轉(zhuǎn)換為對(duì)應(yīng)的字符編碼。
(2)將獲得字符編碼轉(zhuǎn)換為二進(jìn)制
(3)對(duì)二進(jìn)制碼做分組轉(zhuǎn)換,每3個(gè)字節(jié)為一組,轉(zhuǎn)換為每4個(gè)6位二進(jìn)制位一組(不足6位時(shí)低位補(bǔ)0)。這是一個(gè)分組變化的過程,3個(gè)8位二進(jìn)制碼和4個(gè)6位二進(jìn)制碼的長(zhǎng)度都是24位(3*8 = 4*6 = 24)。
(4)對(duì)獲得的4-6二進(jìn)制碼補(bǔ)位,向6位二進(jìn)制碼添加2位高位0,組成4個(gè)8位二進(jìn)制碼。
(5)對(duì)獲得的4-8二進(jìn)制碼轉(zhuǎn)換為十進(jìn)制碼。
(6)將獲得的十進(jìn)制碼轉(zhuǎn)換為Base64字符表中對(duì)應(yīng)的字符。
Base64編碼表
| 索引 | 對(duì)應(yīng)字符 | 索引 | 對(duì)應(yīng)字符 | 索引 | 對(duì)應(yīng)字符 | 索引 | 對(duì)應(yīng)字符 |
| 0 | A | 17 | R | 34 | i | 51 | z |
| 1 | B | 18 | S | 35 | j | 52 | 0 |
| 2 | C | 19 | T | 36 | k | 53 | 1 |
| 3 | D | 20 | U | 37 | l | 54 | 2 |
| 4 | E | 21 | V | 38 | m | 55 | 3 |
| 5 | F | 22 | W | 39 | n | 56 | 4 |
| 6 | G | 23 | X | 40 | o | 57 | 5 |
| 7 | H | 24 | Y | 41 | p | 58 | 6 |
| 8 | I | 25 | Z | 42 | q | 59 | 7 |
| 9 | J | 26 | a | 43 | r | 60 | 8 |
| 10 | K | 27 | b | 44 | s | 61 | 9 |
| 11 | L | 28 | c | 45 | t | 62 | + |
| 12 | M | 29 | d | 46 | u | 63 | / |
| 13 | N | 30 | e | 47 | v |
|
|
| 14 | O | 31 | f | 48 | w |
|
|
| 15 | P | 32 | g | 49 | x |
|
|
| 16 | Q | 33 | h | 50 | y |
|
|
?
應(yīng)用
Base64編碼可用于在HTTP環(huán)境下傳遞較長(zhǎng)的標(biāo)識(shí)信息。在其他應(yīng)用程序中,也常常需要把二進(jìn)制數(shù)據(jù)編碼為適合放在URL(包括隱藏表單域)中的形式。此時(shí),采用Base64編碼具有不可讀性,即所編碼的數(shù)據(jù)不會(huì)被人用肉眼所直接看到,算是起到一個(gè)加密的作用。
然而,標(biāo)準(zhǔn)的Base64并不適合直接放在URL里傳輸,因?yàn)?/span>URL編碼器會(huì)把標(biāo)準(zhǔn)Base64中的“/”和“+”字符變?yōu)樾稳纭?/span>%XX”的形式,而這些“%”號(hào)在存入數(shù)據(jù)庫時(shí)還需要再進(jìn)行轉(zhuǎn)換,因?yàn)?/span>ANSI SQL中已將“%”號(hào)用作通配符。
為解決此問題,可采用一種用于URL的改進(jìn)Base64編碼,它不僅在末尾填充'='號(hào),并將標(biāo)準(zhǔn)Base64中的“+”和“/”分別改成了“-”和“_”,這樣就免去了在URL編解碼和數(shù)據(jù)庫存儲(chǔ)時(shí)所要作的轉(zhuǎn)換,避免了編碼信息長(zhǎng)度在此過程中的增加,并統(tǒng)一了數(shù)據(jù)庫、表單等處對(duì)象標(biāo)識(shí)符的格式。
另有一種用于正則表達(dá)式的改進(jìn)Base64變種,它將“+”和“/”改成了“!”和“-”,因?yàn)椤?/span>+”,“*”以及前面在IRCu中用到的“[”和“]”在正則表達(dá)式中都可能具有特殊含義。
此外還有一些變種,它們將“+/”改為“_-”或“._”(用作編程語言中的標(biāo)識(shí)符名稱)或“.-”(用于XML中的Nmtoken)甚至“_:”(用于XML中的Name)。
?
算法實(shí)現(xiàn)
commons-codec開源包提供了對(duì)于Base64的實(shí)現(xiàn),推薦使用。
<dependency>
? <groupId>commons-codec</groupId>
? <artifactId>commons-codec</artifactId>
? <version>1.10</version>
</dependency>
?
范例
注:在commons-codec包中的Base64這個(gè)類中提供了Base64的編碼、解碼方式。
其中,encodeBase64提供的是標(biāo)準(zhǔn)的Base64編碼方式;encodeBase64URLSafe提供了URL安全的Base64編碼方式(將+ 和 /替換為 - 和 _)。
package org.zp.javase.security.encrypt;
import org.apache.commons.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
public class Base64Demo {
??? public static void main(String[] args) throws UnsupportedEncodingException {
??????? String url = "https://www.baidu.com/s?wd=Base64&rsv_spt=1&rsv_iqid=0xa9188d560005131f&issp=1&f=3&rsv_bp=0&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_sug3=1&rsv_sug1=1&rsv_sug7=001&rsv_sug2=1&rsp=0&rsv_sug9=es_2_1&rsv_sug4=2153&rsv_sug=9";
??????? // byte[] encoded = Base64.encodeBase64(url.getBytes("UTF8")); // 標(biāo)準(zhǔn)的Base64編碼
??????? byte[] encoded = Base64.encodeBase64URLSafe(url.getBytes("UTF8")); // URL安全的Base64編碼
??????? byte[] decoded = Base64.decodeBase64(encoded);
??????? System.out.println("url:" + url);
??????? System.out.println("encoded:" + new String(encoded));
??????? System.out.println("decoded:" + new String(decoded));
??? }
}
?
對(duì)稱加密
算法簡(jiǎn)述
對(duì)稱加密算法是應(yīng)用較早的加密算法,技術(shù)成熟。在對(duì)稱加密算法中,數(shù)據(jù)發(fā)信方將明文(原始數(shù)據(jù))和加密密鑰(mi yao)一起經(jīng)過特殊加密算法處理后,使其變成復(fù)雜的加密密文發(fā)送出去。收信方收到密文后,若想解讀原文,則需要使用加密用過的密鑰及相同算法的逆算法對(duì)密文進(jìn)行解密,才能使其恢復(fù)成可讀明文。在對(duì)稱加密算法中,使用的密鑰只有一個(gè),發(fā)收信雙方都使用這個(gè)密鑰對(duì)數(shù)據(jù)進(jìn)行加密和解密,這就要求解密方事先必須知道加密密鑰。
?
特點(diǎn)
優(yōu)點(diǎn):
計(jì)算量小、加密速度快、加密效率高。
缺點(diǎn):
算法是公開的,安全性得不到保證。
通信雙方每次使用對(duì)稱加密算法時(shí),都需要使用其他人不知道的惟一密鑰,這會(huì)使得通信雙方所擁有的密鑰數(shù)量呈幾何級(jí)數(shù)增長(zhǎng),密鑰管理成為用戶的負(fù)擔(dān)。對(duì)稱加密算法在分布式網(wǎng)絡(luò)系統(tǒng)上使用較為困難,主要是因?yàn)槊荑€管理困難,使用成本較高。
而與公鑰、密鑰加密算法比起來,對(duì)稱加密算法能夠提供加密和認(rèn)證卻缺乏了簽名功能,使得使用范圍有所縮小。
?
原理
對(duì)稱加密要求加密與解密使用同一個(gè)密鑰,解密是加密的逆運(yùn)算。由于加密、解密使用同一個(gè)密鑰,這要求通信雙方必須在通信前商定該密鑰,并妥善保存該密鑰。
對(duì)稱加密體制分為兩種:
一種是對(duì)明文的單個(gè)位(或字節(jié))進(jìn)行運(yùn)算,稱為流密碼,也稱為序列密碼;
一種是把明文信息劃分為不同的組(或塊)結(jié)構(gòu),分別對(duì)每個(gè)組(或塊)進(jìn)行加密、解密,稱為分組密碼。
?
假設(shè)甲乙方作為通信雙方。假定甲乙雙方在消息傳遞前已商定加密算法,欲完成一次消息傳遞需要經(jīng)過如下步驟。
工作模式
以DES算法的工作模式為例,DES算法根據(jù)其加密算法所定義的明文分組的大小(56位),將數(shù)據(jù)分割成若干56位的加密區(qū)塊,再以加密區(qū)塊為單位,分別進(jìn)行加密處理。如果最后剩下不足一個(gè)區(qū)塊的大小,稱之為短塊。短塊的處理方法有填充法、流密碼加密法、密文挪用技術(shù)。
根據(jù)數(shù)據(jù)加密時(shí)每個(gè)加密區(qū)塊見得關(guān)聯(lián)方式來區(qū)分,可以分為以下種工作模式:
(1)? 電子密碼本模式(Electronic Code Book, ECB)
用途:適合加密密鑰,隨機(jī)數(shù)等短數(shù)據(jù)。例如,安全地傳遞DES密鑰,ECB是最合適的模式。
(2)? 密文鏈接模式(Cipher Booki Chaining, CBC)
用途:可加密任意長(zhǎng)度的數(shù)據(jù),適用于計(jì)算產(chǎn)生檢測(cè)數(shù)據(jù)完整性的消息認(rèn)證MAC。
(3)? 密文反饋模式(Cipher Feed Back, CFB)
用途:因錯(cuò)誤傳播無界,可以用于檢查發(fā)現(xiàn)明文密文的篡改。
(4)? 輸出反饋模式(Output Feed Back, OFB)
用途:使用于加密冗余性較大的數(shù)據(jù),比如語音和圖像數(shù)據(jù)。
AES算法除了以上4中模式外,還有一種新的工作模式:
(5)? 計(jì)數(shù)器模式(Counter, CTR)
用途:適用于各種加密應(yīng)用。
本文對(duì)于各種工作模式的原理展開描述。個(gè)人認(rèn)為,作為工程應(yīng)用,了解其用途即可。
?
填充方法
Java中對(duì)稱加密對(duì)于短塊的處理,一般是采用填充方式。
常采用的是:NoPadding(不填充)、Zeros填充(0填充)、PKCS5Padding填充。
ZerosPadding
方式:全部填充為0的字節(jié)
結(jié)果如下:
F1 F2 F3 F4 F5 F6 F7 F8 //第一塊
F9 00 00 00 00 00 00 00 //第二塊
?
PKCS5Padding
方式:每個(gè)填充的字節(jié)都記錄了填充的總字節(jié)數(shù)
結(jié)果如下:
F1 F2 F3 F4 F5 F6 F7 F8 //第一塊
F9 07 07 07 07 07 07 07 //第二塊
?
常用算法
對(duì)稱加密算法主要有DES、3DES(TripleDES)、AES、IDEA、RC2、RC4、RC5和Blowfish等。
?
算法實(shí)現(xiàn)
基于密鑰加密的流程(DES、DESede、AES和IDEA)
DES、DESede、AES和IDEA等算法都是基于密鑰加密的對(duì)稱加密算法,它們的實(shí)現(xiàn)流程也基本一致。步驟如下:
(1)生成密鑰
KeyGenerator kg = KeyGenerator.getInstance("DES");
SecureRandom random = new SecureRandom();
kg.init(random);
SecretKey secretKey = kg.generateKey();
建議使用隨機(jī)數(shù)來初始化密鑰的生成。
?
(2)初始化密碼對(duì)象
Cipher cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
ENCRYPT_MODE:加密模式
DECRYPT_MODE:解密模式
?
(3)執(zhí)行
String plaintext = "Hello World";
byte[] ciphertext = cipher.doFinal(plaintext.getBytes());
?
完整實(shí)例
一個(gè)完整的DES加密解密范例
import org.bouncycastle.util.encoders.Base64;
import org.zp.javase.security.encode.Encode;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
/**
?* @Title DESCoder
?* @Description DES安全編碼:是經(jīng)典的對(duì)稱加密算法。密鑰僅56位,且迭代次數(shù)偏少。已被視為并不安全的加密算法。
?* @Author?victor
?* @Date 2016年7月14日
?*/
public class DESCoder implements Encode {
??? public static final String KEY_ALGORITHM_DES = "DES";
??? public static final String CIPHER_DES_DEFAULT = "DES";
??? public static final String CIPHER_DES_ECB_PKCS5PADDING = "DES/ECB/PKCS5Padding"; // 算法/模式/補(bǔ)碼方式
??? public static final String CIPHER_DES_CBC_PKCS5PADDING = "DES/CBC/PKCS5Padding";
??? public static final String CIPHER_DES_CBC_NOPADDING = "DES/CBC/NoPadding";
??? private static final String SEED = "%%%today is nice***"; // 用于生成隨機(jī)數(shù)的種子
??? private Key key;
??? private Cipher cipher;
??? private String transformation;
??? public DESCoder() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
??????? this.key = initKey();
??????? this.cipher = Cipher.getInstance(CIPHER_DES_DEFAULT);
??????? this.transformation = CIPHER_DES_DEFAULT;
??? }
??? public DESCoder(String transformation)
??????????? throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException {
??????? this.key = initKey();
??????? this.cipher = Cipher.getInstance(transformation);
??????? this.transformation = transformation;
??? }
??? /**
???? * @Title decrypt
???? * @Description 解密
???? * @Author?victor
? ? ?* @Date 2016年7月20日
???? * @param input 密文
???? * @return byte[] 明文
???? * @throws InvalidKeyException
???? * @throws IllegalBlockSizeException
???? * @throws BadPaddingException
???? * @throws InvalidAlgorithmParameterException
???? */
??? public byte[] decrypt(byte[] input) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
??????????? InvalidAlgorithmParameterException {
??????? if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
??????????? cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(getIV()));
??????? } else {
??????????? cipher.init(Cipher.DECRYPT_MODE, key);
??????? }
??????? return cipher.doFinal(input);
??? }
??? /**
???? * @Title encrypt
???? * @Description 加密
???? * @Author?victor
? ? ?* @Date 2016年7月20日
???? * @param input 明文
???? * @return byte[] 密文
???? * @throws InvalidKeyException
???? * @throws IllegalBlockSizeException
???? * @throws BadPaddingException
???? * @throws InvalidAlgorithmParameterException
???? */
??? public byte[] encrypt(byte[] input) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
??????????? InvalidAlgorithmParameterException {
??????? if (transformation.equals(CIPHER_DES_CBC_PKCS5PADDING) || transformation.equals(CIPHER_DES_CBC_NOPADDING)) {
??????????? cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(getIV()));
??????? } else {
??????????? cipher.init(Cipher.ENCRYPT_MODE, key);
??????? }
??????? return cipher.doFinal(input);
??? }
??? /**
???? * @Title initKey
???? * @Description 根據(jù)隨機(jī)數(shù)種子生成一個(gè)密鑰
???? * @Author victor
???? * @Date 2016年7月14日
???? * @Return Key
???? * @throws NoSuchAlgorithmException
???? * @throws NoSuchProviderException
???? */
??? private Key initKey() throws NoSuchAlgorithmException, NoSuchProviderException {
??????? // 根據(jù)種子生成一個(gè)安全的隨機(jī)數(shù)
??????? SecureRandom secureRandom = null;
??????? secureRandom = new SecureRandom(SEED.getBytes());
??????? KeyGenerator keyGen = KeyGenerator.getInstance(KEY_ALGORITHM_DES);
??????? keyGen.init(secureRandom);
??????? return keyGen.generateKey();
??? }
??? private byte[] getIV() {
??????? String iv = "01234567"; // IV length: must be 8 bytes long
??????? return iv.getBytes();
??? }
??? public static void main(String[] args) throws Exception {
??????? DESCoder aes = new DESCoder(CIPHER_DES_CBC_PKCS5PADDING);
??????? String msg = "Hello World!";
??????? System.out.println("原文: " + msg);
??????? byte[] encoded = aes.encrypt(msg.getBytes("UTF8"));
??????? String encodedBase64 = Base64.toBase64String(encoded);
??????? System.out.println("密文: " + encodedBase64);
??????? byte[] decodedBase64 = Base64.decode(encodedBase64);
??????? byte[] decoded = aes.decrypt(decodedBase64);
??????? System.out.println("明文: " + new String(decoded));
??? }
}
結(jié)果:
原文: Hello World!
密文: TtnEu9ezNQtxFKpmq/37Qw==
明文: Hello World!
?
基于口令加密的流程(PBE)
DES、DESede、AES、IDEA這幾種算法的應(yīng)用模型幾乎如出一轍。
但是,并非所有對(duì)稱加密算法都是如此。
基于口令加密(Password Based Encryption, PBE)是一種基于口令加密的算法。其特點(diǎn)是:口令由用戶自己掌管,采用隨機(jī)數(shù)(這里叫做鹽)雜湊多重加密等方法保證數(shù)據(jù)的安全性。
PBE沒有密鑰概念,密鑰在其他對(duì)稱加密算法中是經(jīng)過計(jì)算得出的,PBE則使用口令替代了密鑰。
流程:
?
步驟如下:
(1)產(chǎn)生鹽
SecureRandom secureRandom = new SecureRandom();
byte[] salt = secureRandom.generateSeed(8); // 鹽長(zhǎng)度必須為8字節(jié)
?
(2)根據(jù)密碼產(chǎn)生Key
String password = "123456";
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM);
SecretKey secretKey = keyFactory.generateSecret(keySpec);
?
(3)初始化加密或解密對(duì)象
PBEParameterSpec paramSpec = new PBEParameterSpec(salt, ITERATION_COUNT);
Cipher cipher = Cipher.getInstance(KEY_ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, paramSpec);
?
(4)執(zhí)行
byte[] plaintext = "Hello World".getBytes();
byte[] ciphertext = cipher.doFinal(plaintext);
?
非對(duì)稱加密
算法簡(jiǎn)述
非對(duì)稱加密算法和對(duì)稱加密算法的主要差別在于非對(duì)稱加密算法用于加密和解密的密鑰是不同的。一個(gè)公開,稱為公鑰(public key);一個(gè)保密,稱為私鑰(private key)。因此,非對(duì)稱加密算法也稱為雙鑰加密算法或公鑰加密算法。
?
特點(diǎn)
優(yōu)點(diǎn)
非對(duì)稱加密算法解決了對(duì)稱加密算法的密鑰分配問題,并極大地提高了算法安全性。
?
缺點(diǎn)
算法比對(duì)稱算法更復(fù)雜,因此加密、解密速度都比對(duì)稱算法慢很多。
?
原理
非對(duì)稱加密算法實(shí)現(xiàn)機(jī)密信息交換的基本過程是:甲方生成一對(duì)密鑰并將其中的一把作為公用密鑰向其它方公開;得到該公用密鑰的乙方使用該密鑰對(duì)機(jī)密信息進(jìn)行加密后再發(fā)送給甲方;甲方再用自己保存的另一把專用密鑰對(duì)加密后的信息進(jìn)行解密。
另一方面,甲方可以使用乙方的公鑰對(duì)機(jī)密信息進(jìn)行簽名后再發(fā)送給乙方;乙方再用自己的私匙對(duì)數(shù)據(jù)進(jìn)行驗(yàn)證。
甲方只能用其私鑰解密,由其公鑰加密后的任何信息。 非對(duì)稱加密算法的保密性比較好,它消除了最終用戶交換密鑰的需要。
?
常用算法
DH(Diffie-Hellman,密鑰交換算法)、RSA
?
算法實(shí)現(xiàn)
完整范例
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
public class RSACoder {
??? private final static String KEY_ALGORITHM = "RSA";
??? private KeyPair keyPair;
??? public RSACoder() throws Exception {
??????? this.keyPair = initKeyPair();
??? }
??? public byte[] encryptByPublicKey(byte[] plaintext, byte[] key) throws Exception {
??????? X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
??????? KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
??????? PublicKey publicKey = keyFactory.generatePublic(keySpec);
??????? Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
??????? cipher.init(Cipher.ENCRYPT_MODE, publicKey);
??????? return cipher.doFinal(plaintext);
??? }
??? public byte[] encryptByPrivateKey(byte[] plaintext, byte[] key) throws Exception {
??????? PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
??????? KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
??????? PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
??????? Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
??????? cipher.init(Cipher.ENCRYPT_MODE, privateKey);
??????? return cipher.doFinal(plaintext);
??? }
??? public byte[] decryptByPublicKey(byte[] ciphertext, byte[] key) throws Exception {
??????? X509EncodedKeySpec keySpec = new X509EncodedKeySpec(key);
??????? KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
??????? PublicKey publicKey = keyFactory.generatePublic(keySpec);
??????? Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
??????? cipher.init(Cipher.DECRYPT_MODE, publicKey);
??????? return cipher.doFinal(ciphertext);
??? }
??? public byte[] decryptByPrivateKey(byte[] ciphertext, byte[] key) throws Exception {
??????? PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key);
???? ???KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
??????? PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
??????? Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
??????? cipher.init(Cipher.DECRYPT_MODE, privateKey);
??????? return cipher.doFinal(ciphertext);
??? }
??? private KeyPair initKeyPair() throws Exception {
??????? // KeyPairGenerator類用于生成公鑰和私鑰對(duì),基于RSA算法生成對(duì)象
??????? KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
??????? // 初始化密鑰對(duì)生成器,密鑰大小為1024位
??????? keyPairGen.initialize(1024);
??????? // 生成一個(gè)密鑰對(duì)
??????? return keyPairGen.genKeyPair();
??? }
??? public static void main(String[] args) throws Exception {
??????? String msg = "Hello World!";
??????? RSACoder coder = new RSACoder();
??????? // 私鑰加密,公鑰解密
??????? byte[] ciphertext = coder.encryptByPrivateKey(msg.getBytes("UTF8"), coder.keyPair.getPrivate().getEncoded());
??????? byte[] plaintext = coder.decryptByPublicKey(ciphertext, coder.keyPair.getPublic().getEncoded());
??????? // 公鑰加密,私鑰解密
??????? byte[] ciphertext2 = coder.encryptByPublicKey(msg.getBytes(), coder.keyPair.getPublic().getEncoded());
??????? byte[] plaintext2 = coder.decryptByPrivateKey(ciphertext2, coder.keyPair.getPrivate().getEncoded());
??????? System.out.println("原文:" + msg);
??????? System.out.println("公鑰:" + Base64.encodeBase64URLSafeString(coder.keyPair.getPublic().getEncoded()));
??????? System.out.println("私鑰:" + Base64.encodeBase64URLSafeString(coder.keyPair.getPrivate().getEncoded()));
??????? System.out.println("============== 私鑰加密,公鑰解密 ==============");
??????? System.out.println("密文:" + Base64.encodeBase64URLSafeString(ciphertext));
??????? System.out.println("明文:" + new String(plaintext));
??????? System.out.println("============== 公鑰加密,私鑰解密 ==============");
??????? System.out.println("密文:" + Base64.encodeBase64URLSafeString(ciphertext2));
??????? System.out.println("明文:" + new String(plaintext2));
??? }
}
結(jié)果:
原文:Hello World!
公鑰:MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVN2mWAMdatpo2l8dwavaX2VC8mRleVTdjwjyahsyCE6UxkdqHsKD6Ecq3OBbuJhEfHxnr7MAD_zoE6zalFs7_si09XTgpVFsFCztPXJpPw-rpQdvaaxYEXJHkY07M_DBrxh1URg2gQl9dEDaruIFrZ12ugTwwEkLA1K_LN7yZrwIDAQAB
私鑰:MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJU3aZYAx1q2mjaXx3Bq9pfZULyZGV5VN2PCPJqGzIITpTGR2oewoPoRyrc4Fu4mER8fGevswAP_OgTrNqUWzv-yLT1dOClUWwULO09cmk_D6ulB29prFgRckeRjTsz8MGvGHVRGDaBCX10QNqu4gWtnXa6BPDASQsDUr8s3vJmvAgMBAAECgYBvU1M8LcKOJFQzzNNoRPVLX0AEJXkuzwcvL1hFtbJYjc2eiQHwYFAJokKKpZc-ADqf7HVLdmvfz4h66P3w925hYHjSF3cs6jiibI7fc9lrdrJLMpv44phPlRCiIanD-U6pyN3bZxRl4Giuz5uGL0SVU6Dxh2Sw7mtnvUBbHCyyaQJBAOixpR-t81Qnpdy4jlbZL8ufTTF1TzlSh0NEDB4tlpHlVolVmZB2M-rdJ3nP8fJXazdsGZMP0q38vgiN2HHMtxsCQQCkKWAaA6KxKNbj0mJDSP1p4qUJ4EAcgXBz4B_PKMZa3ZU2CdmFlhlLRRTOIjZX2VC6IjHKWssa-3V2EqBzCSz9AkBsiK9kH1anofaTBOIfUB4i86KltvnE2uGMVmjwioL4eefrFqoR35BHs-99uag4SN4Rc7JaDb9Ot9xLUR3rtniRAkB8dFXEQx9Teie4HmaapjpgzQ_b9eQE-GjdoHvdHQeMGdMmXb9IVGwmsV-9ixhx73IROx1OURkMArmhYyu7KqitAkBkeQ-7AYOIROJnTUSQTMUELUmZFF1Io_SJGXyRYLgDqz7JCmmhfH7sNm8Gcn6f2VWg-U2D9-G5IHO-vHfz2DS6
============== 私鑰加密,公鑰解密 ==============
密文:U2otXypy1Fg4wcXK187xAuOxWM88oORVDJfaNxvG74Q_rqZ-sT4fEZYLZO80KmsWiufkJbD9Gskgkg7dRPRCwG90pRaU3PD9_sTmksN0v8MUwCX2p80zUeG3gWU6BJwMMUZrltJaHFbKn-BhzoNrn3Q-4BJA8lt6-cKtH0TPeN4
明文:Hello World!
============== 公鑰加密,私鑰解密 ==============
密文:O_rknvo12qaFfWieyTI_Ay8_ph49y3V4jJVs1BykpI81GM3ozCPSnOjHbtdWdjPtgJHFfCjbspAnIT2eM4PtJldIJg6k_2HZCmCCaheUj2pxcvkrhb6GdhSlH-K2FhFGAnlxUAp-3tZpYpxzAteEw1-suldelHdikrCV_uXxAEM
明文:Hello World!
?
術(shù)語
明文(Plaintext):指待加密信息。明文可以是文本文件、圖片文件、二進(jìn)制數(shù)據(jù)等。
密文(Ciphertext):指經(jīng)過加密后的明文。密文通常以文本、二進(jìn)制等形式存在。
加密(Encryption):指將明文轉(zhuǎn)換為密文的過程。
解密(Decryption):指將密文轉(zhuǎn)換為明文的過程。
加密密鑰(Encryption Key):指通過加密算法進(jìn)行加密操作用的密鑰。
解密密鑰(Decryption Key):指通過解密算法進(jìn)行解密操作用的密鑰。
信道(Channel):通信的通道,是信號(hào)傳輸?shù)拿浇椤?/span>
?
參考
《Core Java Volume2》
《Java加密與解密技術(shù)》
總結(jié)
以上是生活随笔為你收集整理的[Java 安全]加密算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Code片段 : .properties
- 下一篇: java内部类的定义原则