BFV全同态密码实现和应用:图片加密

BFV算法原理

个人感觉 这个视频 讲得很好

在这里插入图片描述

在这里插入图片描述

上面是根据视频看得重点。

不关心编码,加密的大致步骤如下
源自 https://zhuanlan.zhihu.com/p/638191070

密钥生成

在这里插入图片描述

加密多项式m

在这里插入图片描述

解密

在这里插入图片描述

图片加密

注意:同态性只针对密文,图片只是密文的一种呈现,不具同态性
BFV同态加密,基于Pyfhel库实现,详细参考 Pyfhel的官方说明

在这里插入图片描述

主程序中修改image_path = "kun.jpg"为你要加密的图片,可实现对图片的BFV加解密。

from PIL import Image
import numpy as np
from Pyfhel import Pyfhel

def enc_au(img_array, key):
    # 2*2的数组线性化
    img_L = img_array.flatten().tolist()
    img_array= np.array(img_L,dtype=np.int64)   #一维数组

    #bfv编码和加密
    ptxt_img = key.encodeInt(img_array)
    ctxt_img = key.encryptPtxt(ptxt_img)


    # 将ctxt 转化为 图片列表
    cimg_bytes= ctxt_img.to_bytes()
    cimg_L = [byte for byte in cimg_bytes] #bytes 转化为数组 数值在 0 到 256 范围内

    #图片数组是一维的,转化为二维数组
    one_dimensional_list = cimg_L
    side_length = int(len(one_dimensional_list) ** 0.5)    # 计算最接近正方形的边长
    padding_count = side_length - (len(one_dimensional_list) % side_length)    # 计算最后一行需要填充的个数
    one_dimensional_list += [0] * (padding_count-1)    # 在一维列表末尾填充0
    one_dimensional_list += [padding_count]
    two_dimensional_list = [one_dimensional_list[i:i+side_length] for i in range(0, len(one_dimensional_list), side_length)]
    cimg_array = np.array(two_dimensional_list)

    cimg_array = cimg_array.astype(np.uint8)

    return cimg_array

def dec_au(encrypted_img_array, key):
    enc_arr = encrypted_img_array.astype(np.int64)
    enc_arr = encrypted_img_array.tolist()
    enc_L = encrypted_img_array.flatten().tolist()
    num_del = enc_L[-1]
    enc_L = enc_L[:-1]
    # 去除末尾的256
    for j in range(num_del-1):
        enc_L = enc_L[:-1]

    flag = True
    while ( flag == True):
        for i in range(256):
            if (enc_L[-i-1] != 0):
                flag = False
                break
        if flag == True:
            for i in range(256):
                enc_L = enc_L[:-1] 
        else: break   

    byte_string = bytes(enc_L)

    #创建ctxt2用于存储图片密文
    ptxt2 = key.encode(2)  # plaintexts created from arrays shorter than 'n' are filled with zeros.
    ctxt2 = key.encrypt(ptxt2)  # Alternatively you can use HE.encryptInt(arr2)

    ctxt2.from_bytes(byte_string)

    rctxt  = key.decryptInt(ctxt2 )

    one_dimensional_list = rctxt.tolist()
    side_length = 128   
    two_dimensional_list = [one_dimensional_list[i:i+side_length] for i in range(0, len(one_dimensional_list), side_length)]
    mimg_array = np.array(two_dimensional_list)

    mimg_array = mimg_array.astype(np.uint8)

    return mimg_array

def image_encrypt(image_path, key):
    # 加载 RGB 图片
    rgb_image = Image.open(image_path)
                  
    # 转换为灰度图
    gray_image = rgb_image.convert('L')

    # 映射到 256 灰度级
    gray_image_256 = gray_image.point(lambda x: round(x * 255 / 255))

    img = gray_image_256.resize((128, 128))  # 调整大小

    img_array = np.array(img)

    # 加密过程
    encrypted_img_array = enc_au(img_array, key)

    aaa=encrypted_img_array.tolist()
    encrypted_img = Image.fromarray(encrypted_img_array)
    encrypted_img.save("encrypted_image.png")

    print("2.Image encrypted and saved as encrypted_image.png\n")    

def image_decrypt(encrypted_image_path, key):
    encrypted_img = Image.open(encrypted_image_path)
    encrypted_img = encrypted_img.convert('L')
    encrypted_img_array = np.array(encrypted_img)

    # 解密过程
    decrypted_img_array = dec_au(encrypted_img_array, key)


    decrypted_img = Image.fromarray(decrypted_img_array)
    decrypted_img.save("decrypted_image.png")

    print("3.Image decrypted and saved as decrypted_image.png\n")


def Create_bfvkey():
    HE = Pyfhel()  # Creating empty Pyfhel object
    bfv_params = {
        'scheme': 'BFV',  # can also be 'bfv'
        'n': 2**14,  # Polynomial modulus degree, the num. of slots per plaintext,
        #  of elements to be encoded in a single ciphertext in a
        #  2 by n/2 rectangular matrix (mind this shape for rotations!)
        #  Typ. 2^D for D in [10, 16]
        't': 256,  # Plaintext modulus. Encrypted operations happen modulo t
        #  Must be prime such that t-1 be divisible by 2^N.
        't_bits': 20,  # Number of bits in t. Used to generate a suitable value
        #  for t. Overrides t if specified.
        'sec': 128,  # Security parameter. The equivalent length of AES key in bits.
        #  Sets the ciphertext modulus q, can be one of {128, 192, 256}
        #  More means more security but also slower computation.
    }
    HE.contextGen(**bfv_params)  # Generate context for bfv scheme
    HE.keyGen()  # Key Generation: generates a pair of public/secret keys
    # HE.relinKeyGen()  # Relinearization key generation

    print("\n1. Pyfhel FHE context generation")
    print(f"\t{HE}\n")
    
    return HE

# 主程序

key =  Create_bfvkey()   


image_path = "kun.jpg"
# pkey = 123
# skey = 123

# 加密原始图像
image_encrypt(image_path, key)

# 解密加密后的图像
encrypted_image_path = "encrypted_image.png"
image_decrypt(encrypted_image_path, key)

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
BFV同态加密算法是一种基于多项式环的加密算法,它可以实现同态加密,即在加密的情况下进行运算,得到的结果仍然是被加密的。 以下是BFV同态加密算法的实现过程: 1. 参数设置:选择两个质数p和q,满足p=2*q+1,其中q为大素数。然后再选择一个多项式环R,即R=Z[x]/(x^N+1),其中N是一个2的幂次。还需要确定一个参数t,满足t^2 > N,并且t和q互质。 2. 密钥生成:生成公钥pk和私钥sk。其中,pk包含p、q、t和多项式环R的信息;sk包含多项式s和多项式e的信息,其中s是在R上随机选择的,e是一个小于t的随机整数。 3. 加密:将明文m转化为多项式m(x),然后将m(x)加上一个小于t的随机多项式r(x),得到多项式c(x)=m(x)+r(x)。然后对c(x)进行模p的运算,得到c(x)的模p剩余类c'(x)。最后将c'(x)加密得到密文ciphertext。 4. 解密:将密文ciphertext解密得到多项式c'(x),然后对c'(x)进行模p的运算,得到c'(x)的模p剩余类c''(x)。最后将c''(x)减去多项式s(x),得到多项式m'(x)。由于r(x)是一个小于t的随机多项式,因此m'(x)与m(x)非常接近。将m'(x)转化为明文m即可完成解密。 5. 同态加法:将两个密文ciphertext1和ciphertext2进行同态加法运算,得到密文ciphertext3,即ciphertext3=ciphertext1+ciphertext2。同态加法的过程是将ciphertext1和ciphertext2的多项式c'(x)和c''(x)相加,然后对相加后的多项式进行模p的运算,得到ciphertext3。 6. 同态乘法:将两个密文ciphertext1和ciphertext2进行同态乘法运算,得到密文ciphertext3,即ciphertext3=ciphertext1*ciphertext2。同态乘法的过程比较复杂,需要进行多次运算,具体可以参考相关论文。 以上就是BFV同态加密算法的实现过程。需要注意的是,该算法的安性取决于选取的参数和密钥的生成过程,因此需要谨慎选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值