密碼學(xué)基礎(chǔ)之RSA與不對(duì)稱秘鑰

本文主要通過RSA加解密實(shí)踐,來講述不對(duì)稱秘鑰的特點(diǎn)。

不對(duì)稱秘鑰和RSA

不對(duì)稱秘鑰算法,也叫公鑰密碼算法。
不對(duì)稱秘鑰算法圖示:

不對(duì)稱秘鑰

不對(duì)稱秘鑰的重要特點(diǎn)是加密和解密用的秘鑰不相同。

和對(duì)稱秘鑰算法的比較

不對(duì)稱秘鑰的優(yōu)點(diǎn)
不對(duì)稱秘鑰有一個(gè)很大的好處是可以把公鑰公開,比如Alice要傳送敏感數(shù)據(jù)給Bob,Bob告訴Alice公鑰,Alice用公鑰加密數(shù)據(jù),通過網(wǎng)絡(luò)傳送給Bob,在傳送時(shí)被攻擊者Eric捕獲到,Eric拿到加密的數(shù)據(jù)和公鑰,但不知道私鑰仍無(wú)法破解敏感信息。

哦,這個(gè)看起來很不錯(cuò),比對(duì)稱加密好多了,完全可以取代對(duì)稱加密呀?

等等!等等!小王同學(xué),你先別激動(dòng),我們先了解下不對(duì)稱秘鑰的缺點(diǎn)再說。

不對(duì)稱秘鑰的缺點(diǎn)
不對(duì)稱秘鑰算法的原理并不復(fù)雜,可以從這篇文章對(duì)RSA算法的原理做大概的了解。
RSA等不對(duì)稱秘鑰算法都存在一個(gè)限制是——慢!這個(gè)從原理很容易知道。
慢會(huì)導(dǎo)致不對(duì)稱秘鑰算法另一個(gè)限制——只能加密少量數(shù)據(jù)。
RSA算法,一次加密的數(shù)據(jù)最多和秘鑰長(zhǎng)度相同。但實(shí)際上,RSA算法一般還需要有數(shù)據(jù)填充,比如常用的RSA_PKCS1_PADDING填充,還需要減去11個(gè)字節(jié)。
1024位秘鑰,所能加密的數(shù)據(jù)長(zhǎng)度為:1024 / 8 - 11 = 117字節(jié)。
不對(duì)稱加密和對(duì)稱加密同時(shí)用
如果你需要加密大量的數(shù)據(jù),可以用對(duì)稱加密,對(duì)稱加密的秘鑰用不對(duì)稱加密算法加密保存。HTTPS就是這樣做的。

不對(duì)稱秘鑰的其它用處

不對(duì)稱秘鑰除了可以用加密、解密還可以用于數(shù)字簽名。本文不涉及數(shù)字簽名的知識(shí),主要講述RSA加解密的使用。

RSA算法

生成秘鑰

RSA的公鑰和私鑰需要配對(duì),不能像對(duì)稱加密的秘鑰,可以隨便寫。
可以用OpenSSL生成RSA公鑰和私鑰

openssl genrsa -out private_key.pem 1024
openssl rsa -in private_key.pem -pubout -out public_key.pem
RSA公鑰和私鑰生成

public_key.pem和privte_key.pem都是文本文件,看下內(nèi)容
public_key.pem

-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1t3KRf4oS3sH8PbABbXL1KBYC
nGq4C/yinpfQ2j2eUmZarHuwIMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjg
lAgVEb3el6iU+WZ7nwLub/BNYS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpE
I/0b+EfRSpXDdvU64wIDAQAB
-----END PUBLIC KEY-----

privte_key.pem

-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQD1t3KRf4oS3sH8PbABbXL1KBYCnGq4C/yinpfQ2j2eUmZarHuw
IMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjglAgVEb3el6iU+WZ7nwLub/BN
YS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpEI/0b+EfRSpXDdvU64wIDAQAB
AoGBAJK0odHfPTgBCf8pcaGYkG9xLJsIeutCNOd/GxOWif2yIux2WS8SkasaWd+/
J5iCSD32t4G9dafSNZyvtTPGYUqll4aGXlFqNW8pm16HPQXWrhv1D5LVEEu3zbj+
iNG+gHwB4bISQAOJbnvB6GoFUbDf8VYwkGGlSLGw5D5tulhRAkEA/XBLTfj+5j40
QPfuRIhcBsgxynKJDcmV0sLAIOTBIfSKs5nuYHEVEOcGaxS+nPY3w1ffSUPUdxm0
7L2s+9c0SQJBAPgzLLFvUjM58J/AtklkGyJ3KK5W+jLi/N1PIw7CGYGM2yfFiQLR
ibtJVjTFhLKqDz/BK4lZ9ffU/VNHSApOncsCQQCRBzSgnw9GtGv0jaxUnW+EFgWg
IyDYufW5kOafLCh1BNpmYnztxWhXrsyWdF2Ltr48U8mbxGwN57EIFJar2v+5AkA7
GkSMRAv48tUf1Y4Sz+m+PU3Mph2SPIcmVA/vFb1pIheV0u4bY7Y+iOokStychu52
qhMp8+gkie2BBTpcafgdAkBw8bAzLgmCV8SZEN60x8c2M2Y95CoYOoMLjvQdEfen
IeDmun3DtAPBuStwYNfeQnAHCwvcOJsgDiRLzhys3056
-----END RSA PRIVATE KEY-----

了解秘鑰文件格式

你是否留意到這兩個(gè)文件開頭結(jié)尾的兩行文字的區(qū)別了呢?比如:
public_key.pem的開頭是

-----BEGIN PUBLIC KEY——

而rsa_private_key的開頭是

-----BEGIN RSA PRIVATE KEY——

除了PUBLICPRIVATE區(qū)別外,后者還多了RSA
這表明這兩個(gè)文件的格式不同。PKCS#1格式的RSA公鑰、私鑰文件開頭和結(jié)束的兩行帶RSA字樣,而PKCS#8格式不帶。
有些RSA庫(kù),解密時(shí)需要PKCS#8格式的私鑰文件,可以用下面的命令轉(zhuǎn)換

openssl pkcs8 -topk8 -inform PEM -in private_key.pem -outform PEM -nocrypt>pkcs8_private_key.pem

加解密演示

1. Python RSA加解密演示

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5


def rsa_encrypt(plaintext, key):
    cipher = PKCS1_v1_5.new(RSA.importKey(key))
    return cipher.encrypt(plaintext)


def rsa_decrypt(ciphertext, key):
    cipher = PKCS1_v1_5.new(RSA.importKey(key))
    return cipher.decrypt(ciphertext, '')


if __name__ == '__main__':
    private_key = '''-----BEGIN RSA PRIVATE KEY-----
    MIICXQIBAAKBgQD1t3KRf4oS3sH8PbABbXL1KBYCnGq4C/yinpfQ2j2eUmZarHuw
    IMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjglAgVEb3el6iU+WZ7nwLub/BN
    YS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpEI/0b+EfRSpXDdvU64wIDAQAB
    AoGBAJK0odHfPTgBCf8pcaGYkG9xLJsIeutCNOd/GxOWif2yIux2WS8SkasaWd+/
    J5iCSD32t4G9dafSNZyvtTPGYUqll4aGXlFqNW8pm16HPQXWrhv1D5LVEEu3zbj+
    iNG+gHwB4bISQAOJbnvB6GoFUbDf8VYwkGGlSLGw5D5tulhRAkEA/XBLTfj+5j40
    QPfuRIhcBsgxynKJDcmV0sLAIOTBIfSKs5nuYHEVEOcGaxS+nPY3w1ffSUPUdxm0
    7L2s+9c0SQJBAPgzLLFvUjM58J/AtklkGyJ3KK5W+jLi/N1PIw7CGYGM2yfFiQLR
    ibtJVjTFhLKqDz/BK4lZ9ffU/VNHSApOncsCQQCRBzSgnw9GtGv0jaxUnW+EFgWg
    IyDYufW5kOafLCh1BNpmYnztxWhXrsyWdF2Ltr48U8mbxGwN57EIFJar2v+5AkA7
    GkSMRAv48tUf1Y4Sz+m+PU3Mph2SPIcmVA/vFb1pIheV0u4bY7Y+iOokStychu52
    qhMp8+gkie2BBTpcafgdAkBw8bAzLgmCV8SZEN60x8c2M2Y95CoYOoMLjvQdEfen
    IeDmun3DtAPBuStwYNfeQnAHCwvcOJsgDiRLzhys3056
    -----END RSA PRIVATE KEY-----'''
    public_key = '''-----BEGIN PUBLIC KEY-----
    MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1t3KRf4oS3sH8PbABbXL1KBYC
    nGq4C/yinpfQ2j2eUmZarHuwIMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjg
    lAgVEb3el6iU+WZ7nwLub/BNYS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpE
    I/0b+EfRSpXDdvU64wIDAQAB
    -----END PUBLIC KEY-----'''
    message = 'RSA加解密演示'
    cipher_text = rsa_encrypt(message.encode(encoding="utf-8"), public_key)
    plain_text = rsa_decrypt(cipher_text, private_key)
    print(str(plain_text, encoding='utf-8'))

注意:對(duì)同樣的公鑰和明文進(jìn)行RSA加密,秘文通常是不一樣的,但這不影響解密。

2. iOS 前端加密,Python后端解密演示
私鑰放在移動(dòng)端是非常不安全的,攻擊者可能破解你的iOS或Android程序找到私鑰。很多時(shí)候,都是移動(dòng)前端加密,后端解密。iOS 加密后用base64編碼傳送給后端,即使這個(gè)數(shù)據(jù)被攻擊者捕獲,也無(wú)法獲取敏感數(shù)據(jù)。
iOS RSA加密可以借助Swift-RSAUtils開源庫(kù)。
iOS代碼中需要公鑰需要去掉首行和末行內(nèi)容。

func demo() {
    let text = "RSA加解密演示"
    let pubkey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1t3KRf4oS3sH8PbABbXL1KBYC" +
            "nGq4C/yinpfQ2j2eUmZarHuwIMT9y5ns1lpZZTktGnypvnQjF8c0Rr/cYU53DJjg" +
            "lAgVEb3el6iU+WZ7nwLub/BNYS83zpzrhDE3Qy6qTM3evsUsekBR8x6f6Usl7KpE" + 
            "I/0b+EfRSpXDdvU64wIDAQAB"
    let encryptedData = RSAUtils.encryptWithRSAPublicKey(text.data(using: String.Encoding.utf8)!, pubkeyBase64: pubkey, keychainTag: "")
    if encryptedData != nil {
        let encryptedDataText = encryptedData!.base64EncodedString(options: NSData.Base64EncodingOptions())
        print("\(encryptedDataText)")
    } else {
        print("error")
    }
}

Python 解密

import base64
cipher_text_base64 = iOS提交過來的字符串
cipher_text = base64.b64decode(cipher_text_base64)
plain_text = rsa_decrypt(cipher_text, private_key)

相關(guān)文章

密碼學(xué)基礎(chǔ)之對(duì)稱加密(一)
密碼學(xué)基礎(chǔ)系列

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容