新闻中心
解决密码管理器中的Padding问题

本文旨在解决在使用Python的`Crypto`库进行AES加密时,由于Padding不正确导致的解密失败问题。通过引入自定义的Padding和Unpadding方法,并结合示例代码,详细展示了如何正确地加密和解密密码,并将其安全地存储在文本文件中。同时,也对代码结构和潜在的安全风险提出了改进建议,确保密码管理器的安全性和可靠性。
在使用 Crypto 库进行 AES 加密时,Padding 错误是一个常见的问题,尤其是在处理需要多次加密和解密,并将结果保存到文件中的场景下。 根本原因是AES算法要求加密的数据长度必须是块大小(通常是16字节)的倍数。当数据长度不满足此要求时,需要进行 Padding 填充。如果 Padding 的方式不正确,解密时就会出现 ValueError: Padding is incorrect. 错误。
理解Padding和Unpadding
Padding 是在数据末尾添加额外字节,使其长度达到块大小的倍数的过程。Unpadding 则是解密后,移除这些额外字节,恢复原始数据的过程。Crypto.Util.Padding 模块提供了一些 Padding 和 Unpadding 的方法,但有时使用自定义的方法可能更可靠。
解决Padding问题的示例代码
以下代码展示了如何使用自定义的 Padding 和 Unpadding 方法来解决这个问题。此代码基于 Stack Overflow 上的一个答案,并进行了修改以适应密码管理器的需求。
Shopxp购物系统Html版
一个经过完善设计的经典网上购物系统,适用于各种服务器环境的高效网上购物系统解决方案,shopxp购物系统Html版是我们首次推出的免费购物系统源码,完整可用。我们的系统是免费的不需要购买,该系统经过全面测试完整可用,如果碰到问题,先检查一下本地的配置或到官方网站提交问题求助。 网站管理地址:http://你的网址/admin/login.asp 用户名:admin 密 码:admin 提示:如果您
0
查看详情
import re
import random
import string
from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes
import hashlib
def password_generator(size=10):
if size <= 8:
print("Size must be at least 4")
return None
password = []
while len(password) < size:
password.append(random.choice(string.ascii_lowercase)) # ensure at least one lowercase letter
if len(password) < size:
password.append(random.choice(string.ascii_uppercase)) # ensure at least one uppercase letter
if len(password) < size:
password.append(random.choice(string.digits)) # ensure at least one digit
if len(password) < size:
password.append(random.choice(string.punctuation)) # ensure at least one special character
random.shuffle(password) # shuffle to remove the predictability
return ''.join(password)
def password_checker(password):
if len(password) >= 8:
if bool(re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d])', password)):
print("The password is strong")
else:
print("The password is weak")
else:
print("You h*e entered a short or invalid password.")
# Generate a password
generated_password = password_generator()
print(generated_password)
# Check the generated password
password_checker(generated_password)
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key).digest()
def encrypt_data(self, iv, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return cipher.iv, iv + cipher.encrypt(raw.encode())
def decrypt_data(self, iv, enc):
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return AESCipher._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
# Generate a random 128-bit IV for AES
iv = get_random_bytes(16)
# Generate a random 256-bit key for AES
key = get_random_bytes(32) # s*e this maybe?
Cipher = AESCipher(key)
# Encrypt the generated password
iv, encrypted_password = Cipher.encrypt_data(iv, generated_password)
print(f"Encrypted password: {encrypted_password}")
# Decrypt the encrypted password
decrypted_password = Cipher.decrypt_data(iv, encrypted_password)
print(f"Decrypted password: {decrypted_password}")
# S*e the encrypted password to a file
with open(
'Password.txt',
'a', encoding='utf-8') as f:
f.write(f"{iv.hex()}:{encrypted_password.hex()}\n")
# Read the encrypted password from the file
with open(
'Password.txt',
'r', encoding='utf-8') as f:
for line in f.readlines():
line = line.strip() # Remove the trailing newline character
iv, encrypted_password = line.split(':')
decrypted_password = Cipher.decrypt_data(bytes.fromhex(iv), bytes.fromhex(encrypted_password))
print(f"Decrypted password from file: {decrypted_password}")代码解释:
-
AESCipher 类: 这个类封装了 AES 加密和解密的所有操作,包括初始化、Padding 和 Unpadding。
- __init__: 初始化方法,接收一个密钥,并使用 SHA256 对其进行哈希处理,以确保密钥的安全性。
- encrypt_data: 加密数据的方法,先对数据进行 Padding,然后使用 AES 加密。
- decrypt_data: 解密数据的方法,先使用 AES 解密,然后进行 Unpadding。
- _pad: 自定义的 Padding 方法,将数据填充到块大小的倍数。
- _unpad: 自定义的 Unpadding 方法,移除 Padding 字节。
- 密钥生成: 使用 get_random_bytes(32) 生成一个 256 位的随机密钥。请注意,在实际应用中,需要安全地存储和管理这个密钥。
- 加密和解密流程: 首先创建一个 AESCipher 实例,然后使用 encrypt_data 方法加密密码,并使用 decrypt_data 方法解密密码。
- 文件存储: 将 IV 和加密后的密码以十六进制字符串的形式存储在文本文件中,用冒号分隔。读取文件时,将十六进制字符串转换回字节,然后进行解密。
注意事项和改进建议
- 密钥管理: 密钥的安全存储至关重要。不要将密钥硬编码在代码中,也不要将其存储在与加密数据相同的文件中。考虑使用密钥管理系统或硬件安全模块 (HSM) 来安全地存储密钥。
- 避免硬编码路径: 避免在代码中硬编码文件路径,使用相对路径或配置文件来提高代码的可移植性和安全性。
- 异常处理: 在文件读写和加密解密过程中,添加适当的异常处理,以提高代码的健壮性。
- 使用更安全的文件格式: 虽然文本文件可以用于存储加密数据,但使用二进制文件格式(如 .bin)可能更安全,因为它们不容易被意外编辑或损坏。
- 使用更强的密钥派生函数 (KDF): SHA256 是一种哈希函数,但它不是专门为密钥派生设计的。考虑使用 Argon2、bcrypt 或 scrypt 等 KDF 来从用户密码派生密钥。
- 组织代码结构: 始终将所有导入放在文件的开头,这是一种良好的编码实践。
总结
通过使用自定义的 Padding 和 Unpadding 方法,可以有效地解决 Crypto 库中由于 Padding 不正确导致的解密失败问题。同时,注意密钥的安全存储和管理,以及代码的健壮性和安全性,可以构建一个安全可靠的密码管理器。
以上就是解决密码管理器中的Padding问题的详细内容,更多请关注其它相关文章!
# 管理器
# 泉州seo价格
# 如何优化小红书seo
# 营销推广方案表格
# 临潼区视频营销推广
# 头条seo外推
# 巢湖网站建设选哪家
# cpc推广网站
# 河南网站推广主管
# qq营销推广群
# 金花seo官网
# 自动生成
# 器中
# 文本文件
# 是在
# 不正确
# word
# 文档
# 购物系统
# 自定义
# crypto
# red
# overflow
# 配置文件
# ai
# 字节
# app
# 编码
# go
# git
# python
相关栏目:
【
科技资讯46185 】
【
网络学院92790 】
相关推荐:
如何更改在 Excel 中打开超链接时的默认浏览器
PySpark中高效提取字符串右侧可变长度数字:使用regexp_extract
Win11怎么安装Linux子系统 Win11 WSL2安装Ubuntu及环境配置指南
微博网页版主页入口 微博官方网站免登录访问
LINUX下如何进行磁盘分区_fdisk与parted工具在LINUX中的使用对比
为什么我的微信朋友圈看不到别人的更新_微信朋友圈更新显示异常解决方法
谷歌浏览器无痕模式怎么开 Chrome开启无痕浏览设置方法【教程】
使用J*aScript检测输入元素是否包含在特定类中
b站赚钱渠道_b站收益来源
钉钉视频会议声音异常如何处理 钉钉会议音频修复技巧
抖音未来赚钱的新趋势 2025年值得关注的变现风口分析
qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程
qq邮箱日历功能怎么用_创建日程与会议邀请的技巧
163邮箱官方主页登录 直达网易邮箱登录核心页面
如何在J*a中实现统一对象行为接口_项目大型化时的接口规范化
使用CSS更改登录屏幕输入框中PNG图标颜色的策略与局限性
Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达
红果短剧网页版官网入口 官方最新网址发布
QQ邮箱网页版登录入口 QQ邮箱官方在线使用平台
快手赚钱渠道_快手收益来源
html网页设计源代码怎么运行_运行html网页设计源代码步骤【指南】
如何使用纯J*aScript判断Input元素是否在特定类容器内
Golang如何通过reflect获取匿名字段方法_Golang reflect匿名字段方法访问技巧
J*aScript中localStorage数据的获取、清洗与格式化教程
微信商城在哪里打开【步骤】
c++项目目录结构应该如何组织_c++工程化项目结构规范
C++如何实现一个智能指针_手动实现C++ shared_ptr的引用计数功能
深入理解J*a链表中的IPosition接口与使用
解决Python logging 中 datefmt 导致时间戳固定不变的问题
sublime如何只显示或隐藏特定类型文件_sublime侧边栏文件过滤
海量存储:机器视觉智能化的核心基石
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
优化HTML表单样式:解决输入框焦点跳动与元素间距问题
Fabric模组开发:自定义物品与物品组的现代管理方法
必由学登录入口 必由学官方网站在线访问链接
漫蛙2(台版)官方入口地址 漫蛙2(台版)正版漫画网页端
使用Pandas转换并合并DataFrame:多列映射至统一结构
win11怎么查看应用耗电情况 Win11电池设置查看应用能耗排行榜【优化】
在WordPress中通过REST API获取BasicAuth保护的远程文章
Centos/Linux 系统下安装 composer 的完整步骤
今日头条怎么同步内容到抖音_今日头条内容同步到抖音教程
微博网页版官方账号登录 微博网页版内容浏览使用指南
菜鸟取件码是什么怎么查 最全查询渠道汇总
小红书商家版怎样在笔记嵌入商品卡路径_小红书商家版在笔记嵌入商品卡路径【挂载教程】
AO3最新镜像入口 Archive of Our Own官方平台访问
在J*a里如何理解依赖关系的方向_依赖方向在模块结构中的作用
poki免费入口快捷访问 poki人气小游戏直接玩站点
拼多多赚钱渠道_拼多多收益来源
海棠账号登录入口_登录海棠账户同步阅读记录
在J*a中如何在J*a中使用异常机制记录错误日志_异常日志实践经验


2025-11-16
浏览次数:次
返回列表
while len(password) < size:
password.append(random.choice(string.ascii_lowercase)) # ensure at least one lowercase letter
if len(password) < size:
password.append(random.choice(string.ascii_uppercase)) # ensure at least one uppercase letter
if len(password) < size:
password.append(random.choice(string.digits)) # ensure at least one digit
if len(password) < size:
password.append(random.choice(string.punctuation)) # ensure at least one special character
random.shuffle(password) # shuffle to remove the predictability
return ''.join(password)
def password_checker(password):
if len(password) >= 8:
if bool(re.match(r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z\d])', password)):
print("The password is strong")
else:
print("The password is weak")
else:
print("You h*e entered a short or invalid password.")
# Generate a password
generated_password = password_generator()
print(generated_password)
# Check the generated password
password_checker(generated_password)
class AESCipher(object):
def __init__(self, key):
self.bs = AES.block_size
self.key = hashlib.sha256(key).digest()
def encrypt_data(self, iv, raw):
raw = self._pad(raw)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return cipher.iv, iv + cipher.encrypt(raw.encode())
def decrypt_data(self, iv, enc):
cipher = AES.new(self.key, AES.MODE_CBC, iv)
return AESCipher._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')
def _pad(self, s):
return s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
@staticmethod
def _unpad(s):
return s[:-ord(s[len(s)-1:])]
# Generate a random 128-bit IV for AES
iv = get_random_bytes(16)
# Generate a random 256-bit key for AES
key = get_random_bytes(32) # s*e this maybe?
Cipher = AESCipher(key)
# Encrypt the generated password
iv, encrypted_password = Cipher.encrypt_data(iv, generated_password)
print(f"Encrypted password: {encrypted_password}")
# Decrypt the encrypted password
decrypted_password = Cipher.decrypt_data(iv, encrypted_password)
print(f"Decrypted password: {decrypted_password}")
# S*e the encrypted password to a file
with open(
'Password.txt',
'a', encoding='utf-8') as f:
f.write(f"{iv.hex()}:{encrypted_password.hex()}\n")
# Read the encrypted password from the file
with open(
'Password.txt',
'r', encoding='utf-8') as f:
for line in f.readlines():
line = line.strip() # Remove the trailing newline character
iv, encrypted_password = line.split(':')
decrypted_password = Cipher.decrypt_data(bytes.fromhex(iv), bytes.fromhex(encrypted_password))
print(f"Decrypted password from file: {decrypted_password}")