python-RSA加密与java-Cipher加密适配
在进行login操作时,经常需要对登录密码进行加密,这时涉及到了两种开发语言的加密兼容适配问题。我们先来看java-Cipher加密
【java-Cipher加密介绍】
一、Cipher类提供了加密和解密功能,利用Cipher类可完成des、des3、rsa和aes加密。通过获取Cipher类对象
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
对象对应解释为:“算法/模式/填充模式” -- “DES/CBC/PKCS5Padding”
二、常见有以下参数:
* AES/CBC/NoPadding (128)
* AES/CBC/PKCS5Padding (128)
* AES/ECB/NoPadding (128)
* AES/ECB/PKCS5Padding (128)
* DES/CBC/NoPadding (56)
* DES/CBC/PKCS5Padding (56)
* DES/ECB/NoPadding (56)
* DES/ECB/PKCS5Padding (56)
* DESede/CBC/NoPadding (168)
* DESede/CBC/PKCS5Padding (168)
* DESede/ECB/NoPadding (168)
* DESede/ECB/PKCS5Padding (168)
* RSA/ECB/PKCS1Padding (1024, 2048)
* RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
* RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
(1)加密算法有:AES,DES,DESede(DES3)和RSA 四种
(2) 模式有CBC(有向量模式)和ECB(无向量模式),向量模式可以简单理解为偏移量,使用CBC模式需要定义一个IvParameterSpec对象
(3) 填充模式:
* NoPadding: 加密内容不足8位用0补足8位, Cipher类不提供补位功能,需自己实现代码给加密内容添加0, 如{65,65,65,0,0,0,0,0}
* PKCS5Padding: 加密内容不足8位用余位数补足8位, 如{65,65,65,5,5,5,5,5}或{97,97,97,97,97,97,2,2}; 刚好8位补8位8
代码示例:
private static byte[] encryptByPublic(byte[] data, PublicKey key) throws GeneralSecurityException{Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");cipher.init(Cipher.ENCRYPT_MODE, key);return cipher.doFinal(data);
}
示例代码中padding表示的意思是什么呢?
看下述的一个示例:
RSA/ECB/OEAPWithSHA-1AndMGF1Padding
在SUN JCE是这样解释的:RSA/ECB/OEAPWithSHA-1AndMGF1Padding中的HASH=SHA1 MGF1=SHA1
那接下来我们来了解python的rsa加密。
【python-RSA加密介绍】
一、一般在python中有RSA加密的第三方库有rsa、Crypto和Cryptodemo、Cryptography。
示例代码1:
#!/usr/bin python3
# _*_ coding:utf-8 _*_
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64def encryptDemo(data):with open("./publickey.pem", "rb") as f:public_code = f.read()public_key = RSA.importKey(public_code)cipher = PKCS1_v1_5.new(public_key)encrpt = base64.b64encode(cipher.encrypt(str(data).encode())).decode()return encrpt
在示例代码中采用了Crypto库来实现RSA的加密,引用了PKCS1_v1_5的padding模式,与java Cipher类中的RSA/ECB/PKCS1Padding 等同。
示例代码2:
#!/usr/bin python3
# _*_ coding:utf-8 _*_
import rsa
import base64def encryptDemo(data):with open("./publickey.pem", "rb") as f:public_code = f.read()public_key = rsa.PublicKey.load_pcks1(public_code )encrpt = base64.b64encode(rsa.encrypt(str(data).encode("utf-8"), public_key)).decode()return encrpt
上述两个示例都是通过读取pem文件来处理RSA加密。
二、加密密钥为字符串的处理
一般的加密串
MII89sdJS6KijPS0NB9AtyUVC7BAQEFAAOCAQ8AMIIBCgKCAQEOkISJAH87D7Cb6AvquOFRT8AeI5cscJ********************************************************************************************************************************************************************************7RHCUSDJOAinHDBV
遇到加密密钥为字符串,第一种方式可通过补全pem格式的头部和尾部,如
-----BEGIN PUBLIC KEY-----
MII*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************BUS870B9Ay6BA
-----END PUBLIC KEY-----
示例代码3:
#!/usr/bin python3
# _*_ coding:utf-8 _*_
import rsa
import base64def encryptDemo(data):public_data = "MII89sdJS6KijPS0NB9AtyUVC7BAQEFAAOCAQ8AMIIBCgKCAQEOkISJAH87D7Cb6AvquOFRT8AeI5cscJ********************************************************************************************************************************************************************************7RHCUSDJOAinHDBV"new_data = "-----BEGIN PUBLIC KEY-----\n" + public_data + "-----END PUBLIC KEY-----"public_key = rsa.PublicKey.load_pcks1_openssl_pem(new_data)encrpt = base64.b64encode(rsa.encrypt(str(data).encode("utf-8"), public_key)).decode()return encrpt
第二种方式同base64的编码来加载
示例代码4:
#!/usr/bin python3
# _*_ coding:utf-8 _*_
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64def encryptDemo(data):public_data = "MII89sdJS6KijPS0NB9AtyUVC7BAQEFAAOCAQ8AMIIBCgKCAQEOkISJAH87D7Cb6AvquOFRT8AeI5cscJ********************************************************************************************************************************************************************************7RHCUSDJOAinHDBV"public_key = RSA.importKey(base64.b64encode(public_data))cipher = PKCS1_v1_5.new(public_key)encrpt = base64.b64encode(cipher.encrypt(str(data).encode("utf-8"),public_key)).decode()return encrpt
三、java Cipher类中的RSA/ECB/OAEPWithSHA-256AndMGF1Padding 兼容
首先RSA/ECB/OAEP模式,在python的Crypto或Cryptodemo库中两种方式PKCS1_v1_5和PKCS1_OAEP。
其次在前面我们已经知道了padding模式的解释,它指的是SHA256算法+sha1。
接下来分析在PKCS1_OAEP的new方法源码:
def new(key, hashAlgo=None, mgfunc=None, label=b'', randfunc=None):"""Return a cipher object :class:`PKCS1OAEP_Cipher` that can be used to perform PKCS#1 OAEP encryption or decryption.:param key:The key object to use to encrypt or decrypt the message.Decryption is only possible with a private RSA key.:type key: RSA key object:param hashAlgo:The hash function to use. This can be a module under `Cryptodome.Hash`or an existing hash object created from any of such modules.If not specified, `Cryptodome.Hash.SHA1` is used.:type hashAlgo: hash object:param mgfunc:A mask generation function that accepts two parameters: a string touse as seed, and the lenth of the mask to generate, in bytes.If not specified, the standard MGF1 consistent with ``hashAlgo`` is used (a safe choice).:type mgfunc: callable:param label:A label to apply to this particular encryption. If not specified,an empty string is used. Specifying a label does not improvesecurity.:type label: bytes/bytearray/memoryview:param randfunc:A function that returns random bytes.The default is `Random.get_random_bytes`.:type randfunc: callable"""if randfunc is None:randfunc = Random.get_random_bytesreturn PKCS1OAEP_Cipher(key, hashAlgo, mgfunc, label, randfunc)
在new函数中hashAlgo参数, mgfunc参数默认都是为None,而java Cipher类中的RSA/ECB/OAEPWithSHA-256AndMGF1Padding中要用到SHA256和SHA1
示例代码5:推荐Cryptodome库
#!/usr/bin python3
# _*_ coding:utf-8 _*_
from Cryptodome.Signature import pss
from Cryptodome.Hash import SHA256, SHA1
from Cryptodome.Cipher import PKCS1_OAEP
from Cryptodome.PublicKey import RSA
import base64def encrtypt(data, public_code):public_key = RSA.importKey(base64.b64decode(public_code))cipher = PKCS1_OAEP.new(public_key, hashAlgo=SHA256, mgfunc=lambda x, y:pss.MGF1(x, y, SHA1))encrypt_data = base64.b64encode(cipher.encrypt(str(data).encode())).decode()return encrypt_data
【注】RSA加密是有长度限定的,所以当data长度过长时,需要做分段加密
示例代码6:
#!/usr/bin python3
# _*_ coding:utf-8 _*_
from com import client
from Cryptodome.Signature import pss
from Cryptodome.Hash import SHA256, SHA1
from Cryptodome.Cipher import PKCS1_OAEP
from Cryptodome.PublicKey import RSA
import base64def encrtypt(data, public_code, length):public_key = RSA.importKey(base64.b64decode(public_code))encrypt_data = []cipher = PKCS1_OAEP.new(public_key, hashAlgo=SHA256, mgfunc=lambda x, y:pss.MGF1(x, y, SHA1))for i in range(0, len(str(data)), length):encrypt_data.append(base64.b64encode(cipher.encrypt(str(data)[i:i + length].encode())).decode())return encrypt_data
以上为本次关于python RSA加密与java Cipher类的兼容说明,如有错误之处烦请在评论区指出,也欢迎大家在评论参与讨论。谢谢!
[Cipher部分知识引用] https://blog.csdn.net/SeptDays/article/details/121102385
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
