成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

非對稱加密之RSA是怎么加密的

安全 應用安全
RSA加密是一種非對稱加密??梢栽诓恢苯觽鬟f密鑰的情況下,完成解密。這能夠確保信息的安全性,避免了直接傳遞密鑰所造成的被破解的風險。是由一對密鑰來進行加解密的過程,分別稱為公鑰和私鑰。

前幾天阿粉剛剛說了這個 MD5 加密的前世今生,因為 MD5 也確實用的人不是很多了,阿粉就不再繼續(xù)的一一贅述了,今天阿粉想給大家分享的,是非對稱加密中的一種,那就是 RSA 加密算法。

對稱加密和非對稱加密

在說 RSA 之前,我們得先來說說這個什么事對稱加密,什么又是非對稱加密?

對稱加密指的就是加密和解密使用同一個秘鑰,所以叫對稱加密。對稱加密只有一個秘鑰,作為私鑰。

非對稱加密指的是:加密和解密使用不同的秘鑰,一把作為公開的公鑰,另一把作為私鑰。公鑰加密的信息,只有私鑰才能解密。

那么對稱加密和非對稱加密之間又有什么區(qū)別呢?

  • 對稱加密中加密和解密使用的秘鑰是同一個;非對稱加密中采用兩個密鑰,一般使用公鑰進行加密,私鑰進行解密。
  • 對稱加密解密的速度比較快,非對稱加密和解密花費的時間長、速度相對較慢。
  • 對稱加密的安全性相對較低,非對稱加密的安全性較高。

今天我們來講的就是非對稱加密中的 RSA 加密。

RSA加密是什么?

RSA加密是一種非對稱加密??梢栽诓恢苯觽鬟f密鑰的情況下,完成解密。這能夠確保信息的安全性,避免了直接傳遞密鑰所造成的被破解的風險。是由一對密鑰來進行加解密的過程,分別稱為公鑰和私鑰。

通常情況下個人保存私鑰,公鑰是公開的(可能同時多人持有)。

雖然私鑰是根據公鑰決定的, 但是,我們是沒有辦法根據公鑰來推算出私鑰來的。

為提高保密強度,RSA密鑰至少為500位長。這就使加密的計算量很大。為減少計算量,在傳送信息時,常采用傳統(tǒng)加密方法與公開密鑰加密方法相結合的方式,即信息采用改進的DES或IDEA對話密鑰加密,然后使用RSA密鑰加密對話密鑰和信息摘要。對方收到信息后,用不同的密鑰解密并可核對信息摘要

RSA的加密過程

RSA的加密過程其實并不復雜,

(1)A生成一對密鑰(公鑰和私鑰),私鑰不公開,A自己保留。公鑰為公開的,任何人可以獲取。

(2)A傳遞自己的公鑰給B,B用A的公鑰對消息進行加密。

(3)A接收到B加密的消息,利用A自己的私鑰對消息進行解密。

在這個過程中,只有2次傳遞過程,第一次是A傳遞公鑰給B,第二次是B傳遞加密消息給A,即使都被其他人截獲,也沒有危險性,因為只有A的私鑰才能對消息進行解密,防止了消息內容的泄露。

但是大家有沒有想過,如果我們的消息被截獲了,雖然沒有被解密出來,但是如果說我們的公鑰被攔截,然后將假指令進行加密,然后傳遞給A,這不就涼涼了?那數據是不是就不能稱之為安全了?

不,RSA還有簽名的過程。

簽名過程如下:

(1)A生成一對密鑰(公鑰和私鑰),私鑰不公開,A自己保留。公鑰為公開的,任何人可以獲取。

(2)A用自己的私鑰對消息加簽,形成簽名,并將加簽的消息和消息本身一起傳遞給B。

(3)B收到消息后,在獲取A的公鑰進行驗簽,如果驗簽出來的內容與消息本身一致,證明消息是A回復的。

但是問題又來了,雖然截獲的消息不能被篡改,但是消息的內容可以利用公鑰驗簽來獲得,并不能防止泄露。

那么應該怎么用呢?

其實這就顯的并不是很好理解了 我們是不是可以這么設計:

A和B都有一套自己的公鑰和私鑰,當A要給B發(fā)送消息時,先用B的公鑰對消息加密,再對加密的消息使用A的私鑰加簽名,達到既不泄露也不被篡改,更能保證消息的安全性。

那么 Java 代碼怎么實現 RSA 的呢?代碼如下:

import java.io.ByteArrayOutputStream;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;

public class TestRSA {

/**
* RSA最大加密明文大小
*/
private static final int MAX_ENCRYPT_BLOCK = 117;

/**
* RSA最大解密密文大小
*/
private static final int MAX_DECRYPT_BLOCK = 128;

/**
* 獲取密鑰對
*
* @return 密鑰對
*/
public static KeyPair getKeyPair() throws Exception {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(1024);
return generator.generateKeyPair();
}

/**
* 獲取私鑰
*
* @param privateKey 私鑰字符串
* @return
*/
public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}

/**
* 獲取公鑰
*
* @param publicKey 公鑰字符串
* @return
*/
public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}

/**
* RSA加密
*
* @param data 待加密數據
* @param publicKey 公鑰
* @return
*/
public static String encrypt(String data, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
int inputLen = data.getBytes().length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 對數據分段加密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data.getBytes(), offset, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data.getBytes(), offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
// 獲取加密內容使用base64進行編碼,并以UTF-8為標準轉化成字符串
// 加密后的字符串
return new String(Base64.encodeBase64String(encryptedData));
}

/**
* RSA解密
*
* @param data 待解密數據
* @param privateKey 私鑰
* @return
*/
public static String decrypt(String data, PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] dataBytes = Base64.decodeBase64(data);
int inputLen = dataBytes.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offset = 0;
byte[] cache;
int i = 0;
// 對數據分段解密
while (inputLen - offset > 0) {
if (inputLen - offset > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(dataBytes, offset, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(dataBytes, offset, inputLen - offset);
}
out.write(cache, 0, cache.length);
i++;
offset = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
// 解密后的內容
return new String(decryptedData, "UTF-8");
}

/**
* 簽名
*
* @param data 待簽名數據
* @param privateKey 私鑰
* @return 簽名
*/
public static String sign(String data, PrivateKey privateKey) throws Exception {
byte[] keyBytes = privateKey.getEncoded();
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey key = keyFactory.generatePrivate(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(key);
signature.update(data.getBytes());
return new String(Base64.encodeBase64(signature.sign()));
}

/**
* 驗簽
*
* @param srcData 原始字符串
* @param publicKey 公鑰
* @param sign 簽名
* @return 是否驗簽通過
*/
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(key);
signature.update(srcData.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}

public static void main(String[] args) {
try {
// 生成密鑰對
KeyPair keyPair = getKeyPair();
String privateKey = new String(Base64.encodeBase64(keyPair.getPrivate().getEncoded()));
String publicKey = new String(Base64.encodeBase64(keyPair.getPublic().getEncoded()));
System.out.println("私鑰:" + privateKey);
System.out.println("公鑰:" + publicKey);
// RSA加密
String data = "待加密的文字內容";
String encryptData = encrypt(data, getPublicKey(publicKey));
System.out.println("加密后內容:" + encryptData);
// RSA解密
String decryptData = decrypt(encryptData, getPrivateKey(privateKey));
System.out.println("解密后內容:" + decryptData);

// RSA簽名
String sign = sign(data, getPrivateKey(privateKey));
// RSA驗簽
boolean result = verify(data, getPublicKey(publicKey), sign);
System.out.print("驗簽結果:" + result);
} catch (Exception e) {
e.printStackTrace();
System.out.print("加解密異常");
}
}
}

同樣,當我們看到 RSA 的 Java實現的時候,我們就看到了他的缺點,上來就先定義最大加密明文大小和最大解密密文大小,那么這個 117 是怎么來的?

Java 默認的 RSA 加密實現不允許明文長度超過密鑰長度減去 11(單位是字節(jié),也就是 byte)。也就是說,如果我們定義的密鑰(我們可以通過 java.security.KeyPairGenerator.initialize(int keysize?) 來定義密鑰長度)長度為 1024(單位是位,也就是 bit),生成的密鑰長度就是 1024位 / 8位/字節(jié) = 128字節(jié),那么我們需要加密的明文長度不能超過 128字節(jié) -11 字節(jié) = 117字節(jié)。也就是說,我們最大能將 117 字節(jié)長度的明文進行加密,否則會出問題( javax.crypto.IllegalBlockSizeException: Data must not be longer than 53 bytes 的異常)。

那么我們使用 RSA 的時候應該注意什么內容呢?

1.加密的系統(tǒng)不要具備解密的功能,否則 RSA 可能不太合適,

因為這樣即使黑客攻破了加密系統(tǒng),他拿到的也只是一堆無法破解的密文數據。

2.生成密文的長度和明文長度無關,但明文長度不能超過密鑰長度

不管明文長度是多少,RSA 生成的密文長度總是固定的。但是明文長度不能超過密鑰長度。

也就是阿粉上面說的那個117字節(jié)數,不然就只能等著出現異常了。

關于RSA 你了解了么?

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2020-05-27 10:10:56

對稱加密Hash算法數字簽名

2019-12-11 16:56:37

HTTPS對稱加密Java

2024-12-31 08:00:00

SpringBoot開發(fā)加密

2014-07-07 10:04:32

2023-11-22 16:08:48

2016-11-10 23:51:41

2019-09-23 12:16:02

通信安全加密哈希

2018-07-10 10:29:27

2019-09-11 08:37:16

2010-07-28 10:09:01

2023-09-04 14:00:28

加密密鑰私鑰

2024-11-26 10:01:25

2024-12-31 08:54:38

2011-03-14 10:38:10

SQL Server非對稱密鑰加密

2011-03-14 15:06:49

SQL Server 安全

2022-06-05 23:30:25

AES加密算法

2025-03-04 08:59:16

2015-03-26 11:25:10

對稱加密加密壓縮加密解密解壓

2019-11-21 14:58:34

哈希加密安全

2022-06-01 09:00:56

加密算法密鑰
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 午夜一区二区三区在线观看 | 国产乱精品一区二区三区 | 麻豆精品国产91久久久久久 | 中文字幕综合 | 欧美一区二区三区在线看 | 亚洲一区二区三区免费 | 精品国产欧美 | 亚洲精品欧美精品 | 久热爱 | 日韩精品成人 | 亚洲网在线 | 国产精品一区二区av | 亚洲一区中文字幕 | 这里只有精品999 | 精品国产精品国产偷麻豆 | 欧美日韩福利 | 精品久久网 | 91在线观看 | 在线国产一区二区 | 天天夜碰日日摸日日澡 | 久色激情 | 久久精彩| 国产在视频一区二区三区吞精 | 黑人巨大精品欧美一区二区免费 | 亚洲字幕在线观看 | 岛国精品| av网站在线看 | 蜜桃黄网| 亚洲精品一区二区 | 在线婷婷| 日韩欧美在线播放 | 999视频| 欧美三级在线 | 久久久久久久久久久高潮一区二区 | 国产精品视频免费观看 | 国产精品久久九九 | 成人免费视频观看 | 国产不卡一区在线观看 | 精品毛片 | 在线a视频网站 | 天天射夜夜操 |