添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

在进行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 base64
def 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 base64
def 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 base64
def 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 base64
def 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 to
      use 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 improve
      security.
    :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_bytes
    return 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 base64
def 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 base64
def 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

$ python3 main.py 注意事项: RSA 属公钥密码体制,所以在运行过程中会在本地生成 rsa_pubkey.txt 和 rsa_privkey.txt 文件,用于存储公钥和私钥。 密钥的位数默认为1024位,填充规则选用 PKCS1-PADDING,即对1024位的密钥,其字节为128位,对输入的数据将会采用 128 - 11 = 117 字节为一个分组进行加密,不足117字节的将会选择随机数进行填充。 输入明文不用在意个数,最好是在200字符以内。 加密结果会用 Base64 进行 Cipher_pkcs1_v1_5直接加密短字符串没有问题,但是加密长字符串就会报错,需要进行分块加密,分块解密 非分段加密 def encrypt(message): RSA加密 :param message: with open(‘private.pem’) as f: key = f.read() rsakey = RSA.importKey(key) cipher = Ci... 纯Python RSA实现 是纯Python RSA实现。 根据PKCS#1版本1.5,它支持加密和解密,签名和验证签名以及密钥生成。 它既可以用作Python库,也可以在命令行中使用。 该代码主要由Sybren A.Stüvel编写。 可以在找到文档。 对于所有更改,请检查 。 使用以下方法下载并安装: pip install rsa 或从下载它。 源代码在维护,并根据获得 由于Python在内部存储数字的方式,很难(即使不是不可能)使纯Python程序免受定时攻击的影响。 该库也不例外,因此请谨慎使用。 请参阅了解更多信息。 开发环境的设置 python3 -m venv .venv . ./.venv/bin/activate pip install poetry poetry install 发布新版本 . ./.venv/bin/activate poetry p import base64 from Crypto.Hash import SHA256, SHA1 from Crypto.Cipher import PKCS1_OAEP, PKCS1_v1_5 from Crypto.Signature.pss import MGF1 from Crypto.PublicKey import RSA def rsa_encrpyt(text, publickey): text = bytes(text, encoding='utf-8') 公钥用来加密和验证签名,私钥用来解密和签名。 A有公钥publicA,私钥privateA, B有公钥publicB,私钥privateB。 A给B发送信息,用B的公钥加密保证数据安全,用自己的私钥签名。 B收到消息,用A的公钥验证签名,确保信息是A发送过来的,用自己的私钥解密。 在​《RFC-8017 PKCS #1 RSA Cryptorgraphy Specification Version 2.2》规范的第7章节中规定了RSA算法在PKCS1填充和OAEP填充模式下,对于原文数据的约束。本节内容主要起因于工作中遇到的一个问题,对于应用开发者来说,实际上并不需要我们去深度学习RSA算法实现,我们只要知道RSA算法加解密应用场景,不同场景下规范定义的数据封装格式,及签名/验签/加密/解密方案约束即可。这里概括下本节主要内容,用于学习总结,手动翻译,个中存在错误纰漏欢迎批评指正。 from Crypto import Random from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5 from Crypto.PublicKey import RSA class RsaCode: rsa_private_key = """-----BEGI... RSA加密是一种非对称加密,通常使用公钥加密,私钥解密,私钥签名,公钥验签。在公开密钥密码体制中,加密密钥(即公开密钥)PK是公开信息,而解密密钥(即秘密密钥)SK是需要保密的.RSA算法通常是先生成一对RSA密钥,其中之一是保密密钥,由用户保存;另一个为公开密钥,可对外公开,甚至可在网络服务器中注册。RSA是一种公钥密码算法,加密算法是将明文m(m以下是关于RSA生成公钥私钥、加密、解密、加签、... 接口数据使用了RSA加密和签名?一篇文章带你搞定! ​ 很多童鞋在工作中,会遇到一些接口使用RSA加密和签名来处理的请求参数,那么遇到这个问题的时候,第一时间当然是找开发要加解密的方法,但是开发给加解密代码,大多数情况都是java,c++,js等语言实现的,加解密的代码虽然有了,但是咱们身为一个测试,使用python做的自动化,并不是什么语言都会,这个时候就会比较尴尬了,看着这一团加解密... 1、前言很多朋友在工作中,会遇到一些接口使用RSA加密和签名来处理的请求参数,那么遇到这个问题的时候,第一时间当然是找开发要加解密的方法,但是开发给加解密代码,大多数情况都是java,c++,js等语言实现的,加解密的代码虽然有了,但是咱们身为一个测试,使用python做的自动化,并不是什么语言都会,这个时候就会比较尴尬了,看着这一团加解密的代码,自己却不知从何下手,再去找开发给写个python版...