=Start=
缘由:
简单整理一下 Blowfish 密码算法的相关知识,方便后面有需要的时候参考。
正文:
参考解答:
Blowfish 密码算法介绍
Blowfish是一个对称密钥分组密码算法,由 Bruce Schneier 于1993年设计。Blowfish算法由于分组长度太小已被认为不安全,Schneier更建议在现代应用中使用 Twofish 密码。或者使用 AES 算法进行加解密。
Schneier设计的Blowfish算法用途广泛,意在替代老旧的DES及避免其他算法的问题与限制。Blowfish刚刚研发出的时候,大部分其他加密算法是专利所有的或属于商业(政府)机密,所以发展起来非常受限制。Schneier则声明Blowfish的使用没有任何限制,任何国家任何人任何时候都可以随意使用Blowfish算法。
Blowfish的填充模式
块(分组)密码只能对固定长度的数据块进行处理,而消息的长度通常是可变的,因此不同的工作模式对应的填充模式不同,当您选择NONE不填充时,则要保证加密文本长度为8的倍数,否则出现解密/加密异常。
- 填充区别:在ECB、CBC工作模式下最后一块要在加密前进行填充,其它不用选择填充模式;
- 填充模式:Blowfish支持的填充模式为PKCS5、PKCS7和NONE。其中PKCS7标准是主流加密算法都遵循的数据填充算法。Blowfish标准规定的区块长度为固定值64Bit,推荐PKCS7。
Blowfish密钥KEY和初始化向量IV
初始化向量IV可以有效提升安全性,但是在实际的使用场景中,它不能像密钥KEY那样直接保存在配置文件或固定写死在代码中,一般正确的处理方式为:在加密端将IV设置为一个8位的随机值,然后和加密文本一起返给解密端即可。
- 区块长度:Blowfish标准规定区块长度只有一个值,固定为64Bit,对应的字节为8位;
- 密钥KEY:密钥长度区间为32-448,对应4-56位,该字段不能公开传输,用于加密和解密;
- 初始化向量IV:该字段可以公开,用于将加密随机化。同样的明文被多次加密也会产生不同的密文,避免了较慢的重新产生密钥的过程,初始化向量与密钥相比有不同的安全性需求,因此IV通常无须保密。然而在大多数情况中,不应当在使用同一密钥的情况下两次使用同一个IV,一般初始化向量IV为8位的随机值。
Blowfish 的主要特点
- Block Cipher: Blowfish is a block cipher encryption algorithm that operates on 64-bit blocks of plaintext at a time. Blowfish 是一种分块密码加密算法,每次对 64 位的明文块进行操作。
- Symmetric Key Encryption: Blowfish uses a symmetric key encryption system, meaning that the same key is used for both encryption and decryption. Blowfish 使用对称密钥加密系统,这意味着加密和解密都使用相同的密钥。
- Variable Key Size: Blowfish allows for variable key sizes of up to 448 bits, making it more secure compared to other encryption algorithms. Blowfish 允许高达 448 位的可变密钥大小,与其他加密算法相比更加安全。
- Feistel Cipher: Blowfish uses the Feistel Cipher structure, which splits the plaintext into two halves and then iteratively encrypts each half using a series of mathematical operations. Blowfish 使用 Feistel 密码结构,它将明文分成两半,然后通过一系列数学运算对每一半进行迭代加密。
用 Python 进行 Blowfish 加解密
from Crypto.Cipher import Blowfish
from struct import pack
import base64
def blowfish_str(encrypt_or_decrypt, msg, key):
if encrypt_or_decrypt == "encrypt":
bs = Blowfish.block_size
key = bytes(key, encoding='utf-8')
cipher = Blowfish.new(key, Blowfish.MODE_CBC)
plaintext = msg.encode('utf-8')
plen = bs - len(plaintext) % bs
padding = [plen]*plen
padding = pack('b'*plen, *padding)
ciphertext = cipher.iv + cipher.encrypt(plaintext + padding) #加密返回的数据类型是 bytes 类型
return ciphertext
elif encrypt_or_decrypt == "decrypt":
bs = Blowfish.block_size
key = bytes(key, encoding='utf-8')
ciphertext = base64.b64decode(msg) #和加密之后的操作有关
iv = ciphertext[:bs]
ciphertext = ciphertext[bs:]
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
plaintext = cipher.decrypt(ciphertext) #解密返回的数据是 bytes 类型
last_byte = plaintext[-1]
plaintext = plaintext[:- (last_byte if type(last_byte) is int else ord(last_byte))]
return plaintext
def encrypt_decrypt_blowfish():
key = 'password_here'
with open('raw_data.txt') as fp:
plaintext = fp.read()
ciphertext = blowfish_str('encrypt', plaintext, key)
with open('data_blowfish_encrypt.txt','w') as fp:
fp.write(base64.b64encode(ciphertext).decode())
with open('data_blowfish_encrypt.txt') as fp:
encrypt_data = fp.read()
decrypt_data = blowfish_str('decrypt', encrypt_data, key)
# decrypt_data = blowfish_str('decrypt', base64.b64encode(ciphertext), key)
with open('data_blowfish_decrypt.txt','w') as fp:
fp.write(decrypt_data.decode())
#encrypt_decrypt_blowfish
from Crypto.Cipher import Blowfish
from Crypto import Random
def encrypt(key, plaintext):
iv = Random.new().read(Blowfish.block_size)
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
padded_plaintext = _pad_string(plaintext)
ciphertext = cipher.encrypt(padded_plaintext)
return iv + ciphertext
def decrypt(key, ciphertext):
iv = ciphertext[:Blowfish.block_size]
cipher = Blowfish.new(key, Blowfish.MODE_CBC, iv)
padded_plaintext = cipher.decrypt(ciphertext[Blowfish.block_size:])
plaintext = _unpad_string(padded_plaintext)
return plaintext
def _pad_string(s):
padding_size = Blowfish.block_size - len(s) % Blowfish.block_size
padding = chr(padding_size) * padding_size
return s + padding
def _unpad_string(s):
padding_size = ord(s[-1])
return s[:-padding_size]
key = b'secret_key'
plaintext = 'This is a secret message.'
encrypted_data = encrypt(key, plaintext)
print('Encrypted data:', encrypted_data.hex())
decrypted_data = decrypt(key, encrypted_data)
print('Decrypted data:', decrypted_data)
参考链接:
Blowfish (cipher)
https://en.wikipedia.org/wiki/Blowfish_(cipher)
Understanding Blowfish Encryption Algorithm | 2023 #有代码,nice
https://cyberw1ng.medium.com/understanding-blowfish-encryption-algorithm-2023-24eb8f69f85b
How to decrypt using Blowfish in Pycrypto?
https://stackoverflow.com/questions/35042164/how-to-decrypt-using-blowfish-in-pycrypto
Blowfish
https://pycryptodome.readthedocs.io/en/latest/src/cipher/blowfish.html
https://pycryptodome.readthedocs.io/en/latest/src/cipher/classic.html#cbc-mode
Blowfish 加密算法
https://leeyuxun.github.io/Blowfish%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95.html
Blowfish加密算法
https://try8.cn/tool/cipher/blowfish
A simple Python implementation for Blowfish Encryption Algorithm
https://github.com/ananya2407/Blowfish-Algorithm
=END=