【加密算法基础——RSA加密特点分析及解密方式】
RSA 加密特点分析
根据上一篇的RSA的加密呈现的结果,我们来分析一下RSA加密的特点,方便见到此种密钥的时候能够知道是RSA加密,并能快速解密。
公钥
RSA公钥:
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvaWwqYY8ag69+f9Yucnp
esK98wvfj8eKuVTCrg0Z7NpFeuggulf4mg2djTtIM2ENhmRBoaopJuXfdR8AEFp+
iNsCCJ/ffZZ8hAk65DkYOhW/tO60PHndCvU5vVQ/2nwjFTgQJFODyZdQIZDFZIkm
q7co/G+FZ9DRj+5tmMw0cEMQZaSdicpdmezOcafxrwCTgpCnr6ePmFLzN6ZW/xBb
DPO2FvBxonRooUp7uWXiAGuVI7uEMIzacovNrcI4HP0ZI1EXWQFBAFRNhOoSAKVS
nmt9RiC+0GsEHGAayi7ueBVybJFj4YOHaY9wFK/ElXBcZ8By/Li916QJgNWqttVJ
ZQIDAQAB
-----END PUBLIC KEY-----
这是RSA加密用的PEM格式的公钥。我们知道公钥是用于加密的,这种PEM
格式的特点是带标头和尾部,并用BASE64
格式编码。如果密钥不是PEM格式,考虑将密钥转换为 PEM 格式,因为 PEM 格式在许多工具和库中具有良好的兼容性。
私钥
RSA私钥:
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvaWwqYY8ag69+f9YucnpesK98wvfj8eKuVTCrg0Z7NpFeugg
ulf4mg2djTtIM2ENhmRBoaopJuXfdR8AEFp+iNsCCJ/ffZZ8hAk65DkYOhW/tO60
PHndCvU5vVQ/2nwjFTgQJFODyZdQIZDFZIkmq7co/G+FZ9DRj+5tmMw0cEMQZaSd
icpdmezOcafxrwCTgpCnr6ePmFLzN6ZW/xBbDPO2FvBxonRooUp7uWXiAGuVI7uE
MIzacovNrcI4HP0ZI1EXWQFBAFRNhOoSAKVSnmt9RiC+0GsEHGAayi7ueBVybJFj
4YOHaY9wFK/ElXBcZ8By/Li916QJgNWqttVJZQIDAQABAoIBAAE6X/AG7ObTtFNM
6iPjjq/reQxYGPcdAYSVsN4kd7ft6/bTzZNnEsryvbOZpjAcIF7bg7wsDyqecyhB
SfOmfaoLUC5yasQi49N5HVHV8ZqnYdP1iqGSGLqa+9PNkoxfhEBCdKMIeGTkPLoQ
oRb4k7f22yE4y30fTDhpmxfmKScFWLayuj5V0SySW+0JK5YwT/5fB0CNADar/SRg
JF5SYFVKZ/sFEJvIXnbz4PqQkdIw7X6//pxd4Q0Jk269rYK3SLo4+2vX5Uhucifs
PEbjYz0CPeDOOlC3UsVPVTB+5ejGHext0PxuoxrlEEbrMZsi6GJmgmsl0ihWvjsy
k9idTscCgYEAyEvYsYznWSFOXrC9wKIofZgeLsoFmHicM/b3j6r5dz+goC9a5iZc
bLMdQOiFQzBNxJPJ/24117yCpFUPcSLZhDdH2hQYOxw/zevNIFR9V4rQUTMidOI0
y6fo67u+1k+j2ew3oABBqibnJD4G7VKylRxDo5BW0uGMVz5KKpjeHc8CgYEA8mOu
ci0jbfeHYXQ8QSZgC5ByBQWYdxWYXK9jaHMb/HaIjtPiY/fxw3jTUO0BHa+ozXBZ
6TJS+fY1nRyuUQ8xxKVflD3Pfa54Bh1BV/yDYv4bePuqj7hlfzGBYcPnWroYxDHH
kX0Mp+qXow5bgDCWfjKuBrssAH7YLfNxp4JDxosCgYALU46ra6ZheequnBv+2qyj
fYinaLEsUBW1MpAJRcfZoHV62XKwdRbg5rgOxZdTl1WuehUAJsFQs85HcK/w2+Gl
AmNDx8MfBJfvExiEbYKxAp6JGPUn2urVYWdgfTtrbxF670qt95W/A3gqqn9FyFlk
6TZB95WRU0PWYyVah054LQKBgEEXEZ5pjq0WHo3GB/Q62OniFSxSD1pTO0IQezJu
TuKh9hPcxFuyFoM2bBC8RGNza3IXrJ1ZvTyQqF8Td6Ae4296NUt6ucB3XJXPv19g
WOv5bukzM986Vk8svSDC2drcRJBTCdOA8CgbcDMCRQIMii1DcMYv9yX+6hCU4j1o
Vsj3AoGAbBMvPAQTBVnz5qwvTcdgkwoM2ALB/eBsjGaeBgNqDkerVTs2cY/AEJIO
+56+cAyk54w6KkbkcmGsha1Qg7NfnrohgjXPBFRh2f5SsBcrdDxYdLiLVpc/Y+B7
kHg+/hcDWtDKrbsCOJt4fV7lKRwIpdK9p6aYVWFsSvd2jgcF8dA=
-----END RSA PRIVATE KEY-----
一般私钥比公钥要长,公钥只用于加密,解密的时候用不到公钥。都是PEM格式的。
用来解密的时候,一般也要将私钥转换成PEM格式。
填充方式
如果保证你的私钥是正确的,密文是完整的,那离解密还差一步就是填充方式。直接关系到能不能正确解密。
RSA 加密中,填充方式用于增强加密的安全性。填充的主要目的是防止某些类型的攻击,同时确保加密数据的长度符合 RSA 算法的要求。RSA一般有两种填充方式:
PKCS#1 v1.5
- 概述: 这是 RSA 最早的填充标准之一,广泛用于许多应用。
- 安全性: 尽管使用广泛,但它对某些攻击(例如选择明文攻击)不够安全。
- 使用场景: 常用于与旧系统或库的兼容性。
- 解密一般又三种方式可以选择:
OAEP (Optimal Asymmetric Encryption Padding)
- 概述: OAEP 是一种更安全的填充方式,旨在抵御多种攻击。
- 安全性: 提供更好的安全性,尤其是在处理敏感数据时。它通过将消息与随机数据结合来增加复杂性。
- 使用场景: 推荐在新的应用程序和系统中使用,特别是在加密敏感数据时。
只有知道填充方式,我们在解密的时候才能正确的选择解密算法。当然有时候我们只能拿到密文和私钥,这时候就要尝试用不同的填充方式去尝试了。
解密
如果保证你的私钥是正确的,密文是完整的,那就可以尝试用私钥来解密了,至于填充方式,可以用遍历的方式去尝试。
- 在线工具:网上有很多免费的在线解密工具,可以实现私钥自动PEM格式化,不同的填充方式选择。比较方便,但是有时候由于不同网站的实现水平有限,不一定能保证一定能成功解密。
- openssl命令:openssl 命令行工具可以用于解密 RSA 加密的消息。
openssl rsautl -decrypt -inkey private_key.pem -in ciphertext.in -out decrypted.out
rsautl
: 指定使用 RSA 工具。-in file
input file-out file
: output file-inkey file
: input key-keyform arg
: private key format - default PEM-pubin
: input is an RSA public-certin
: input is a certificate carrying an RSA public key-ssl
: use SSL v2 padding-raw
: use no padding-pkcs
: use PKCS#1 v1.5 padding (default)-oaep
: use PKCS#1 OAEP-sign
: sign with private key-verify
: verify with public key-encrypt
: encrypt with public key-decrypt
: decrypt with private key-hexdump
: hex dump output-engine e
: use engine e, possibly a hardware device.-passin arg
: pass phrase source
如果密文是BASE64编码的,这个命令是无法处理的,必须先将BASE64编码的输入文件进行解码:
base64 -d RSAcipher.b64 > RSAcipher.bin
这个命令处理base64
解码要求.b64
文件必须不能换行,否则会报错误base64: invalid input
所以不是太方便。
当然对于密钥的PEM格式,如果存在空格开头,换行,合并行是没有问题的。PEM格式的要求比较低,只要保证头和尾的标识符即可
- 代码实现:比较方便的是python脚本实现多填充模式尝试解码:
代码里的密文和私钥的格式要求就比较灵活了。
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5, PKCS1_OAEP
import base64def rsa_decrypt_v1_5(ciphertext: str, private_key: str) -> str:# 读取私钥private_key = RSA.import_key(private_key)# 创建解密器cipher = PKCS1_v1_5.new(private_key)# 解密密文decrypted_message = cipher.decrypt(base64.b64decode(ciphertext), None)return decrypted_message.decode('utf-8')def rsa_decrypt_oaep(ciphertext: str, private_key: str) -> str:# 读取私钥private_key = RSA.import_key(private_key)# 创建解密器cipher = PKCS1_OAEP.new(private_key)# 解密密文decrypted_message = cipher.decrypt(base64.b64decode(ciphertext))return decrypted_message.decode('utf-8')# 示例密文和私钥
ciphertext = """e2MYJDQu56PS7Z2YGZdUScmWuspeOKpP8JTZ4/VXd7+bu1osViTP0+trZMrBg0rFrGqWQGQ4brfgaqErGiNsTAM5JoJ+d1m0xhpVii92KEgGX/zmy9jaB5Hd4n6r3xvE9+rthRgUq9cF8ryTCYBgZ/O50/LmoiF0uqi6prdLSowxQzionFt1aYcD0ERhbIl2w4+Qsl/7urTEvPuKrkzPoeoEGN6LAAX07qmgQ8r+z5hRNcf5qPK3e2Lzjk6D/PH/KwteAvMZNnB8yxG0lp643HtsIjzM6yfME3pl3fPKFgjcvLGttbMASWwWU7WmHBhl9L7aUeR0rBldD6wg9lqWcg=="""
private_key = """-----BEGIN RSA PRIVATE KEY-----MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDE+C1ieKHKwK49H5Z6n7d9LNk6wpeR7XfK0IkK8LxQ+vg99BIWaOrvGlKFrGTImtqlRVQVfFU1woYmOyD4CGZcBir5NdM2YLNTRgZtBOguYKKNp8kfVuh4Qv2NsDoCDzVS7GngSbalHC/w5bdT2PipvQjY8vN6rmELTCPTt279Vev3TvlF5nBhr/NpbwnKhqZSmzt9xXJ//iXiKV5StH4IEqyt6g1YRU9MAngstVMEI2V1CgrpFC56yPq/4fk7ppAgczNefHV8oSf18f8GInQm491fXFTC6eWBcJqs4SeaKjXbVBgafx/yeM+2vRZ1ZrfTikth8iFGxeYHjY+qIe0xAgMBAAECggEAUWz5MhaFZ/Bsd0c6KXoiXARwzvpHt2NQXM8FgDjR2LZPbikaWxpHWM3sZGdGiKl/jsgQwQsTnLRMSbyy3eZ3Dj7cgAZwyK+EIn41xNa89wMq392HZsXCN4kWEX9TE6ve0ud5w2clsq7q4K7OMULmVSEY6brRzZsN8iIpQ2o231Huk1SoBBTNMEvq4pyVyinWrA0vuXQQwkWK4v6ucLoO56roGntQxGNH4z/4Zd1PADeC8Q91/vEtIV8z+2dsEEqh8Mtu3XiGLCPBett+8d82bYxE4UjHbb4FvNg/B7BKMBpa8rITKRCl1mUjhr3zk4/1Ecs2bElGucsQ00WDbMrM4wKBgQDlxnenSiC/TL8gRLH50+B9VldA6KaJS8jm4+E0rHB1gZYftkyITtKtb9X/x/FXulf7sfBtqCwmK+zSHPEH+pttfCxuYLA11Sp2xcJfnNY64HtWs5YUPH+7lp6TSnDDKSknCakR9WmZiRjb8HeknPf3C+Si/TekBLjUPFumRAh9ZwKBgQDbczH9mcb5aLmXz/FHcQrLb3+vZjtFPC4hH9Ijos/nClAV1rIEZRIUIyW2eJodJh6N6enHEk0+86ikwRbnjXOtljoQTAcvpVQtmoRfpmTqiHvryRCuQK0PFA1AmENK/I2KwzOFwPaPrRK8IAYatKOa+ybKwB0YaWdiCrVsLSSJpwKBgECT5f8TW17IgBLem7KeNMKlKIKqoFuH/B/APgQizryHvhyNjLbmiFmMS/XGSPMiASZRHUSEdlwIDlgDIE7gxRwhQQ+Ihx2qGnQlInrixmbnvmJguLZZRoD/VPQKgOSoxdMd6PGOKq6nFGCEFewi3aIGKq0QQ7oKRbQIfq2dA1HTAoGAEShcjDtttypc+GWls7Q+59D75rbTg4JFCQn34Blmr+W6hTqYCIfudeyZkj6zrfvA/89+G7Zum7FpShhethP1K2lHeOa42RzQDBC8sM3Nrhilt7WsvDMKVNd4gchl2oMMfgDtElQX8vvRLyxBzey5rfBdBBUpMTNshdnYfXC6HpkCgYEAyrJDBRNOoXccHFdzWxQeKg2lqtXh9NIqpBMUqPM8wmbcweaxtlasNX1cAwIUz8zdPUlJlz8DWPjP6PbxWxVceYeBQkWRknLuPvhUg2jawSEQF5aV6Cs5i4ToOTNp39AU1MfztfQYqdTJ8z66h2tqMG99lHebCN9V2XwLDdZxzsw=
-----END RSA PRIVATE KEY-----"""try:decrypted_message_v1_5 = rsa_decrypt_v1_5(ciphertext, private_key)print("Decrypted message using PKCS1_v1_5:", decrypted_message_v1_5)
except ValueError as e:print("Decryption with PKCS1_v1_5 failed:", e)try:decrypted_message_oaep = rsa_decrypt_oaep(ciphertext, private_key)print("Decrypted message using PKCS1_OAEP:", decrypted_message_oaep)
except ValueError as e:print("Decryption with PKCS1_OAEP failed:", e)
运行结果:
Decrypted message using PKCS1_v1_5: PvT7uAKe9LCyjJr++tyjNjQGIHkqkGkPMNIPcFBeJOs=Decryption with PKCS1_OAEP failed: Incorrect decryption.
这个密文用PKCS1_v1_5
的填充方式解开了,看起来是一个AES加密的密钥,而且密钥是用BASE64编码。
总结
总之,只要保证密文和密钥是正确的,一般用脚本去逐个尝试填充方式去解密是没有问题的。但是一定要注意,Base64编码出现的字符串到底是先以base64的格式解,还是直接用uft-8的方式解,这直接关系到是否能解开密文。所以要知道加密者是怎么编码的。