Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

简单位运算加解密实现 #239

Open
soapgu opened this issue Mar 18, 2024 · 0 comments
Open

简单位运算加解密实现 #239

soapgu opened this issue Mar 18, 2024 · 0 comments
Labels

Comments

@soapgu
Copy link
Owner

soapgu commented Mar 18, 2024

  • 按位取反加密

这是一个最简单的加解密方式,直接再执行相同操作就可以恢复原文,非常简单。

代码里面是执行~操作符即可。我们看一下代码原理

byte_value = b'a'  # 这是一个ASCII码对应'a'字符的字节对象

print(byte_value[0])
# 提取第一个(也是唯一一个)字节,并进行按位取反
inv_byte = ~byte_value[0]
print(inv_byte)

执行结果为97和-98

学过ASCII编码的都知道,97就是a的编码,但是求反后-98是什么鬼,其实这是用补码的形式来表示

我们用二进制来表达下再看看

97 : 0110 0001
-98 : 1001 1110

是不是有感觉了。问题是我如果要操作文件内容的加密,就必须转为无符号整型,就是8位二进制。所以转为0~255范围数据。

代码如下

byte_value = b'a'  # 这是一个ASCII码对应'a'字符的字节对象

def bitwise_not_encrypt( input : int ):
    print(f"input byte:{input}")
    output = ~input & 0xFF
    # Python内部自动处理了符号扩展,因此得到的结果仍是在0-255之间的数字
    # 由于Python内建的int类型是足够大的,它能存储任何这样的小整数而无需担心溢出问题
    print(f"output byte:{output}")
    return output

# 提取第一个(也是唯一一个)字节,并进行按位取反
print("encrypt>>>>>>>")
encrypt = bitwise_not_encrypt(byte_value[0])
print("decrypt>>>>>>>")
decrypt = bitwise_not_encrypt(encrypt)

文件操作相关代码

from Crypto.Random import get_random_bytes
import binascii
import os
import argparse
import time


parser = argparse.ArgumentParser(description='Process some files.')
parser.add_argument('-f', '--input-file', required=True, help='The input file')

args = parser.parse_args()

print(f"Input file: {args.input_file}")

ENCRYPT_SIZE = 1024
BLOCK_SIZE = 16 * 1024
download_path = args.input_file
output_filename = f"encrypt_{args.input_file}"

#print(f"key lenght:{len(binascii.unhexlify(keys))}")

in_file_length = os.path.getsize(download_path)
block_count = in_file_length / BLOCK_SIZE
print(in_file_length)
start_time = time.time()
count = 0
with open(download_path, 'rb') as in_file:
    with open(output_filename, 'wb') as out_file:
        # 1. write mess 1k data first
        out_file.write( get_random_bytes(1024) )
        # 2. read 1k data
        head = in_file.read(ENCRYPT_SIZE)
        # 3. aes encrypt and write
        #hex_string = binascii.hexlify(head).decode()
        #print(f"head content:{hex_string}")
        crypted_chunk = bytes([~byte & 0xFF for byte in head])
        out_file.write(crypted_chunk)
        # 4. copy other part file
        head_time = time.time() - start_time
        print(f"加密头时间: {head_time} 秒")
        while content := in_file.read(BLOCK_SIZE):
            out_file.write(content)

out_file_length = os.path.getsize(output_filename)
print(f"encrypt ok,size {out_file_length}")
end_time = time.time()
run_time = end_time - start_time
print(f"按位取反加密运行时间: {run_time} 秒")

解密过程是完全对称的,这里就略过

其中有个计算机概念非常重要就是补码,还是有必要好好了解一下的

0 ^ 0 = 0
1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
  • 异或的特性

异或运算法则具有自反性、交换性和互补性

A ^ 0 = A
A ^ A = 0
(A ^ B) ^ C = A ^ (B ^ C) 
 (B ^ A) ^ A = B ^ 0 = B  
  • 加解密算法
from itertools import cycle

def xor_cipher(text, key):
    encrypted_text = bytes([(c^k) for c, k in zip(text, cycle(key))])
    return encrypted_text

def xor_decipher(encrypted_text, key):
    # 加密和解密使用的是同一函数,因为异或运算具有相反可逆性
    return xor_cipher(encrypted_text, key)

plaintext = b"Hello, World!"

key = b'shgbit'


encrypted = xor_cipher(plaintext, key)
print("Encrypted Text:", encrypted)
decrypted = xor_decipher(encrypted, key)
print("Decrypted Text:", decrypted)
  • 文件替换方式加解密

对于大文件的加解密,文件的复制是一个很大的负担,如果我们只是部分加密可以使用快速替换的方式

但是需要满足下面条件

  • 加密前后文件大小不变
  • 对称加解密

同时文件还有一个模式读写模式来实现操作

from itertools import cycle
import os
import argparse
import time

def xor_cipher(text, key):
    #encrypted_text = ''.join(chr(ord(c) ^ ord(k)) for c, k in zip(text, cycle(key)))
    encrypted_text = bytes([(c^k) for c, k in zip(text, cycle(key))])
    return encrypted_text


parser = argparse.ArgumentParser(description='Process some files.')
parser.add_argument('-f', '--input-file', required=True, help='The input file')

args = parser.parse_args()

print(f"Input file: {args.input_file}")

ENCRYPT_SIZE = 1024
download_path = args.input_file

#print(f"key lenght:{len(binascii.unhexlify(keys))}")

in_file_length = os.path.getsize(download_path)
print(in_file_length)
start_time = time.time()
count = 0
with open(download_path, 'rb') as in_file:
    # read 1k data
    head = in_file.read(ENCRYPT_SIZE)
    # aes encrypt and write
    crypted_chunk = xor_cipher(head,b"shgbit")
    

with open(download_path, 'r+b') as out_file:
    out_file.seek(0)
    out_file.write(crypted_chunk)    

end_time = time.time()
run_time = end_time - start_time
print(f"按位异或加(解)密运行时间: {run_time} 秒")

看运行结果

guhui@guhuideMacBook-Pro RsaDemo % python3 xor_quick_encrypt.py -f film.mkv  
Input file: film.mkv
16342579412
按位异或加(解)密运行时间: 0.00012111663818359375 秒
guhui@guhuideMacBook-Pro RsaDemo % python3 xor_quick_encrypt.py -f film.mkv
Input file: film.mkv
16342579412
按位异或加(解)密运行时间: 0.00012183189392089844 秒

16G的电影文件也是秒编秒解

相关文件模式参考

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant