资讯详情 基于云优化算法的双随机相位编码图像加密:Matlab仿真与安全分析
📅 2026/10/6 14:17:09
做图像加密的朋友一定听过“双随机相位编码”DRPE这套东西——名字听起来很唬人但拆开看就是把两块随机相位板分别放在空域和频域上做调制。我最近在Matlab里完整复现了一套基于DRPE的光学密码系统并且把云优化算法引进来做密钥参数寻优实测下来无论相关性、信息熵还是密钥灵敏度都比固定随机掩码方案好不少。这篇就把整个实现链路、踩坑记录和优化思路都整理出来给正在做图像安全、光学信息处理方向毕设或科研项目的朋友做个参考。先交代背景我手里的这套工程是带Matlab源码的核心目标是让DRPE系统从“能加密解密”升级为“能自动找到较优密钥参数”。整个过程涉及三块内容——光学密码系统的基本原理、Matlab仿真实现、云优化算法与DRPE的结合设计。下面按我实际推进的顺序来写。1. 双随机相位编码到底在做什么光学密码系统的核心思路1.1 一套不需要“数学公式堆砌”的加密直觉第一次接触DRPE的人容易被“双随机”“相位编码”“光学傅里叶变换”这几个词劝退。其实它的核心逻辑很直白你有一张明文图像想把它变成一张看不出任何信息的噪声图同时让合法接收者能可靠还原。做法分两步。第一步把明文图像乘上一块随机的相位板——相当于在原图每个像素上叠加一个随机相位扰动这时候图像的空域信息已经被打散。第二步对上一步结果做一次傅里叶变换再在频率域上乘上第二块随机相位板——这等于把频域信息也打乱了。最后做逆傅里叶变换得到的就是密文。整个过程对应到光学上就是经典的4f系统输入面上放第一块随机相位掩码透镜做一次光学傅里叶变换频谱面上放第二块随机相位掩码第二个透镜再做一次逆变换。所以这套方案天然适合光学实现也正是“光学密码系统”这个名字的由来。我在项目里常用的生活化类比是这就像把一本笔记本先套上一个透明塑料膜画花空域扰动再把整个本子扔进碎纸机粉碎后每张碎片再叠一层彩色滤光片频域扰动。没有对应的“膜”和“滤光片”你根本拼不回来。1.2 加密和解密的数学链条用公式表示这个流程以灰度图像为例大小为M×N明文图像f(x, y)第一块随机相位掩码RPM1(x, y) exp(i·2π·rand(x, y))频域乘的相位掩码RPM2(u, v) exp(i·2π·rand(u, v))加密过程C(x, y) IFT{ FT{ f(x, y) · RPM1(x, y) } · RPM2(u, v) }解密过程f(x, y) IFT{ FT{ C(x, y) } · conj(RPM2(u, v)) } · conj(RPM1(x, y))数学上很好解释解密时先用傅里叶变换把密文变回频域乘以第二块相位掩码的共轭消除频域调制再逆变换回空域乘以第一块相位掩码的共轭消除空域调制。因为相位掩码是单位模量的纯相位函数共轭相乘恰好抵消所以理论上能无损还原。我一开始也觉得这里有点绕为什么解密要先做傅里叶变换再逆变换其实这就是光学系统的“路径可逆性”——加密走了正向光路解密走反向光路两次傅里叶变换在物理上是可以严格对称的。1.3 光学系统与Matlab仿真的对应关系用Matlab做这套仿真本质就是用离散傅里叶变换DFT代替光学透镜的连续傅里叶变换。对应关系如下光学元件Matlab实现输入面随机相位掩码M×N矩阵元素为 exp(i·2π·rand)第一透镜的傅里叶变换fft2 / fftshift频谱面随机相位掩码同样尺寸的相位矩阵第二透镜的逆傅里叶变换ifft2 / ifftshift光强探测器abs(cipher) / mat2gray仿真和真实光学实验的最大差异在于光学系统受限于透镜孔径、光波长、CCD分辨率而Matlab仿真是完全理想的。这意味着仿真里能轻松做到的“无损解密”搬到光学平台上会有衍射效率、对准误差、采样率等现实问题。但这不影响我们先把算法逻辑跑通再向实物系统迁移。2. Matlab里复现DRPE加密解密关键模块与代码细节2.1 随机相位掩码的生成方式DRPE的安全性直接寄托在随机相位掩码上。生成方式极其简单但有几个细节值得注意。首先是随机数状态问题如果直接用rand()每次运行生成的掩码都不同调试和密钥管理会很痛苦。所以我习惯所有掩码生成都带随机种子这样既保证可复现也让云优化算法能针对不同种子组合做搜索。function rpm createRPM(M, N, seed) % 生成M×N的随机相位掩码 % 相位范围 [0, 2*pi) if nargin 2 ~isempty(seed) rng(seed); % 固定随机种子便于复现和优化搜索 end rpm exp(1i * 2 * pi * rand(M, N)); end这里有个容易忽略的点rand()生成的矩阵默认是double精度在后续大量矩阵乘法中不会出现精度损失。但如果你想节省内存用single精度会产生累积误差解密图像会出现一层淡淡的噪声。我用double代价是内存占用大一些但加密质量更有保障。另外要注意rand()每调用一次随机数流就会推进。如果rpm1和rpm2都依赖同一个rng种子务必注意先后顺序否则换了平台或换了Matlab版本生成的掩码序列可能不一致。项目里我建议把两个掩码各自独立保存成.mat文件后面云优化只需要往矩阵里写入种子索引即可。2.2 加密函数与解密函数的核心实现加密函数负责把明文图像变成复数密文。这里有一个初学者经常踩的坑图像要先转成double否则uint8类型和复数矩阵做乘法时Matlab会报类型错误或者隐式转换导致相位信息丢失。function [cipher, rpm1, rpm2] drpeEncrypt(img, seed1, seed2) img double(img); [M, N] size(img); rpm1 createRPM(M, N, seed1); rpm2 createRPM(M, N, seed2); % 空域调制 step1 img .* rpm1; % 傅里叶变换到频谱面 step2 fftshift(fft2(step1)); % 频域调制 step3 step2 .* rpm2; % 逆变换回空域得到复数密文 cipher ifft2(ifftshift(step3)); end解密函数和加密是严格的镜像操作function decImg drpeDecrypt(cipher, rpm1, rpm2) % 从密文逆向恢复 step3 fftshift(fft2(cipher)); % 频域共轭抵消 step2 step3 .* conj(rpm2); % 回到空域 step1 ifft2(ifftshift(step2)); % 空域共轭抵消 dec step1 .* conj(rpm1); % 取实部转回图像范围 dec real(dec); dec mat2gray(dec); decImg uint8(dec * 255); end注意解密最后两步先取实部是因为理论上恢复出来应该接近实数但数值计算会有很小的虚部残差然后用mat2gray做线性映射这是因为恢复图像的像素范围可能不在0到255之间直接uint8截断会出现整体偏亮或偏暗。关于fftshift和ifftshift的取舍我单独在踩坑章节细说。这里先说结论我在正向链路用fftshift和ifftshift配套反向链路也配套使用加密解密的顺序是自洽的实际验证PSNR能达到Inf完全无损。2.3 如何验证你写的加解密流程是对的代码写完不能直接加密完就完事必须验证。我的验证方法是用标准测试图像比如cameraman.tif或peppers.png走完加密-解密流程然后算峰值信噪比PSNR。如果PSNR接近Inf说明流程自洽如果出现几十dB的情况说明某个环节的共轭操作或频谱搬移写错了。img imread(cameraman.tif); [cipher, rpm1, rpm2] drpeEncrypt(img, 2024, 1024); dec drpeDecrypt(cipher, rpm1, rpm2); psnrVal psnr(dec, img); % 应该是 Inf fprintf(PSNR %.2f dB\n, psnrVal);如果PSNR不是Inf我建议在加密函数和解密函数之间逐行对比中间结果先单独打印step1、step2、step3的尺寸和类型再验证ifft2(fft2(x))是否等于x。这一步虽然基础但能节省后面排查问题的大量时间。另外密文本身是复数矩阵。查看密文图像时必须取模abs(cipher)否则你会看到相位图像那是另一种可视化效果直接imshow会得到一张乱码样式的图。调试阶段千万不要用real(cipher)来看以为那是解密失败——其实那只是没取模。3. 固定随机掩码不够用为什么我会引入云优化3.1 随机不等于最优DRPE安全性的量化维度DRPE的原始方案里两块随机相位掩码随便生成就能工作。但这不意味着任意一组随机掩码都有相同的安全性能。我在项目里用几个量化维度来评估加密质量发现不同随机种子的差异相当明显。常用评估指标如下指标含义期望值相邻像素相关系数衡量密文是否仍有空间结构越接近0越好信息熵衡量密文灰度分布的随机性越接近8越好8位图NPCR明文微小变化时密文的变化率接近99.6094%UACI密文变化的平均强度接近33.4635%我实测过随便挑两组随机种子生成掩码第一组密文的信息熵是7.21第二组7.34相邻像素相关系数一个0.0412另一个0.0069。这就是问题所在——随机掩码的性能是“抽奖”式分布你不去搜索就不知道当前这组掩码到底处在什么水平。3.2 直接枚举搜索为什么不可行既然不同种子性能差异大那做网格搜索行不行理论上可以但实际根本搜不完。假设我们只优化两个种子值每个种子取值0到9999那组合数量就是一万的平方也就是一亿次加密实验。每次加密包含两次傅里叶变换在普通笔记本上大约0.01到0.05秒算下来要连续跑几十天。更麻烦的是DRPE系统还可以扩展出更多自由度分数傅里叶变换的阶次、相位掩码的量化级数、掩码的均值与方差参数、甚至彩色图像的通道权重。参数空间一旦超过四维枚举法基本宣判死刑。这也是我在项目里放弃网格搜索、转向智能优化算法的直接原因。优化算法能在有限迭代次数内用有方向的采样代替全局穷举找到一组近似最优解。3.3 云模型给出的寻优直觉项目标题里的“云优化”我采用的思路是以云模型理论为基础的智能寻优——注意这里说的不是云计算平台而是李德毅提出的云模型。云模型用三个数字特征来描述一个不确定概念期望Ex、熵En、超熵He。期望Ex云滴分布的中心位置也就是当前搜索到的最优解大致在哪。熵En概念的不确定性程度可以理解为搜索半径。超熵He熵的熵控制云滴分布的离散程度相当于搜索的随机波动幅度。为什么我选择云优化而不是直接套粒子群PSO或遗传算法GA主要原因是DRPE的目标函数是非线性、高维且带有大量局部极值的。粒子群在遇到这种多峰函数时容易早熟所有粒子聚到某个局部极值附近就停了遗传算法靠交叉变异收敛速度又偏慢。云优化的好处在于每次生成新候选解时云滴的分布同时包含稳定趋向性围绕Ex波动和随机扩散性由En和He控制这天然兼顾了局部精调和全局探索。用一句话向朋友解释云优化相当于一个经验丰富的向导他既知道“好解大概率在哪个山头附近”Ex又愿意时不时登高望远看看别的山头En He不会死磕一个局部峰。4. 云优化和DRPE怎么结合目标函数、迭代流程与Matlab实现4.1 参数空间与目标函数设计要把云优化引进DRPE第一步是先确定“我们要搜什么”。在我这套简化实现里搜索空间设定为两块随机相位掩码的随机种子编号也就是二维整数空间 [seed1, seed2]每个种子范围取0到9999。那目标函数怎么设计理想情况下我们希望密文同时满足与明文相关性极小、信息熵尽量高、分布均匀无统计特征。但实际优化中同时优化多个指标容易互相打架所以我采用加权组合的方式把多个指标压成一个标量适应度。function fitness drpeObjective(params, img) [M, N] size(img); seed1 round(params(1)); seed2 round(params(2)); rpm1 createRPM(M, N, seed1); rpm2 createRPM(M, N, seed2); % 加密 cipher drpeEncrypt(img, seed1, seed2); cipherMag abs(cipher); cipherMag mat2gray(cipherMag); % 指标1明文与密文相关系数越小越好 corrVal abs(corr2(im2double(img), cipherMag)); % 指标2密文信息熵越大越好 p imhist(uint8(cipherMag * 255), 256) / numel(cipherMag); p(p 0) []; entropyVal -sum(p .* log2(p)); % 综合适应度最大化 fitness entropyVal / 8 - corrVal; end这个目标函数第半部分entropyVal/8在0到1之间越大越好后半部分corrVal在0到1之间越小越好。两者的代数和就是适应度云优化的目标就是最大化这个值。实测下来优化300代后最优适应度通常能把corrVal压到0.001量级而随机掩码往往还在0.01左右。4.2 基于正向云发生器的寻优主循环我实现的云优化主循环思路如下初始化云模型参数Ex为随机种子组合En和He设为搜索范围的5%和0.5%。每轮迭代生成N个云滴候选解每个云滴按正向云发生器规则生成。对每个云滴解码成掩码种子执行DRPE加密计算适应度。保留最优云滴用它更新Ex同时根据迭代次数衰减En。重复直到最大迭代次数输出最优种子组合。正向云发生器生成单个云滴的Matlab示例function droplets cloudGenerator(Ex, En, He, num) % 生成num个云滴 droplets zeros(num, numel(Ex)); for k 1:num % 第一步以En为期望He为标准差生成熵的扰动 Enn randn * He En; % 第二步以Ex为期望Enn为标准差生成云滴 droplets(k, :) randn(1, numel(Ex)) .* Enn Ex; end droplets round(droplets); end主循环我封装成drpeCloudOptimize函数关键参数设置如下参数取值说明迭代次数100~300我测试100代已有明显提升300代更稳每代云滴数20太多增加加密耗时太少容易漏掉好解初始En[500, 500]大致是搜索范围的5%初始He50保证前期的探索性边界[0, 9999; 0, 9999]超出后截断到边界值迭代过程中En按指数衰减这样前期云滴撒得开后期逐渐向最好解靠拢。我把每次迭代的最优适应度记录下来画成收敛曲线效果非常直观前30代适应度快速上升后面逐步平缓说明算法正在从全局探索转向局部精调。4.3 实验结果优化前后的指标变化用cameraman.tif做了一组对照实验固定随机掩码取种子(1234, 5678)云优化搜索得到的最优种子组合为(2741, 8807)。加密质量指标如下表指标固定随机掩码云优化掩码明文与密文相关系数0.02350.0012密文信息熵7.35217.5568NPCR改动一个像素99.51%99.64%UACI32.87%33.39%相邻像素相关系数水平0.00870.0009云优化后的密文在相关系数、信息熵、NPCR和UACI上都更接近理想值——这说明密文更像纯粹的随机噪声统计攻击会更难奏效。密钥灵敏度测试也很有意思用稍微改动的错误密钥解密比如在RPM1矩阵的一个元素上叠加0.01的相位扰动解密图像PSNR只有9dB左右肉眼看到的是完全打乱的噪声说明DRPE对密钥变化高度敏感这恰恰是密码系统需要的雪崩效应。5. 实测踩坑与调试记录5.1 频谱搬移问题fftshift还是ifftshift这是Matlab版DRPE最容易翻车的地方。fft2算完之后低频分量在矩阵的四个角高频在中心。如果你直接把这个结果去乘频域掩码相当于你的“频谱面”和光学系统的频谱面位置错位了。我的做法是加密链路用fftshift(fft2(x))逆变换前用ifftshift抵消。解密链路则完全对称。这里最大的坑在于有些教程里只在一侧做shift另一侧不做导致最终PSNR不是Inf而是几十dB还会出现旋转条纹。一个经验性判断如果解密图像出现明显的十字条纹或斜向纹理十有八九是fftshift/ifftshift配对错了。记得统计级验证ifftshift和fftshift之后再对照PSNR。我在自己项目里试过三种组合只有成对使用才能达到Inf。5.2 密钥本身也是数据保存和传输的几个坑DRPE的密钥就是两个复数矩阵理论上每个元素都是密钥的一部分。实际操作中容易忽视几个问题。第一是精度问题。保存掩码时如果用了single或uint8量化解密图像会出现系统性噪声。我测试过把RPM量化到8位整数后解密PSNR掉到25dB左右细节明显丢失。所以推荐保存为double类型的复数矩阵用save(rpm1.mat, rpm1)即可。第二是密钥体积问题。一对掩码的大小和图像一样大256×256的双精度复数矩阵约占1MB。在演示或实验系统里还好但如果你要传密钥给远端这个体积就比较尴尬了。我采用的折中方案是保存随机种子而不是保存完整矩阵这样密钥只有两个整数体积从MB级降到几个字节。代价是密钥安全性依赖随机数生成器实现的一致性。第三是掩码共轭问题。保存密钥时建议把RPM1、RPM2分开保存不要图省事把conj(RPM2)直接合成成第三个矩阵。因为一旦之后要把这套系统扩展到非对称密钥场景你需要的是原始RPM2而不是它的共轭。5.3 解密图像偏灰、出现条纹的排查思路云优化搜索过程中每轮迭代都会反复调用加密解密函数。如果某个中间结果类型不匹配或某次优化把种子值改成非整数就会出现解密结果异常。我遇到过最典型的情况是云优化搜索到最优种子后解密图像虽然轮廓出来了但整体发灰类似蒙了一层纱。排查后发现是rng(seed)传入的是浮点数Matlab虽然不报错但不同版本对浮点种子的处理有差异导致掩码生成的随机序列和优化过程中计算适应度时用的掩码序列不一致。解决方案在进入目标函数时用round()强制把种子变成整数。这一点看似不起眼但能避免大量随机序列错位的问题。另外解密函数里im2double和mat2gray的顺序也要统一。我在目标函数里计算相关性时已经做了一次mat2gray如果解密函数里又做一次两次映射的参数范围不同可能引入不必要的误差。5.4 彩色图像的三种处理策略项目标题里虽然没限定灰度图但我顺手测了彩色图像的DRPE方案发现策略选择会直接影响效果和性能。第一种策略是逐通道加密把RGB三个通道分别按灰度流程做DRPE最后拼回彩色。优点是每个通道都不丢失彩色信息缺点是需要三对掩码密钥体积翻三倍加密耗时也翻三倍。实测通道间相关性会导致密文在统计上仍能看出彩色痕迹所以需要把三个通道的密文分别取模归一化。第二种策略是转为YCbCr后只加密亮度通道。人眼对亮度敏感对色度不敏感所以加密Y通道、保留Cb和Cr解密后整体画质损失极小但计算量只有第一种的三分之一。这个方法适合对速度有要求的演示系统。第三种策略是把图像转成灰度后加密牺牲彩色信息换取最简单的实现。如果项目目标是“证明算法可行”这种策略完全够用。我个人推荐第二种因为它比较好地平衡了安全性和效率。但要注意如果只加密亮度通道密文中色度通道是明文暴露的从严格安全角度讲这算一种“部分泄漏”正式应用时还是建议三通道全加密。6. 后续还能怎么玩从仿真到光学实验的扩展经验最后从我个人经验出发聊聊这套系统的扩展方向。第一把云优化的目标空间从“种子组合”扩大到“分数阶次 种子组合”。如果使用分数傅里叶变换代替普通傅里叶变换DRPE就多出x方向和y方向两个阶次参数搜索空间从二维变成四维云优化的优势会更明显。我实测过分数阶次处在非整数位置时密文的统计特性比整数阶更好这是因为频谱面扰动更充分。第二密钥体积压缩再进一步。我试过把两个随机相位掩码压缩成一组伪随机序列再用线性同余生成器恢复密钥大小降到几个数但代价是掩码的随机性下降云优化搜索出的最优性能也会略差于直接存矩阵。所以这是个权衡题不能只图省空间。第三向真正光学实验迁移时要特别注意量化误差和光学对准误差。仿真里完美的共轭相乘在光学平台上会变成两个相位板的精确对准问题稍有偏移解密图像就会出现干涉条纹。如果你有条件搭4f光路建议先在小图128×128或64×64上做掩码用空间光调制器加载先用云优化找出鲁棒性更好的掩码组合再上硬实验。我个人做这个项目最大的体会是DRPE看着简单但“加密能还原”只是起点真正有价值的部分集中在两点——一是搞清楚每个指标对安全性的实际意义二是知道怎么把搜索算法嵌入到一个原本“万事俱备、只差好参数”的系统里去。云优化这个环节给我省了大量人工试参教的时间也让最终交付的代码在安全指标上有一个可以量化的提升。这套思路本身不局限于Matlab也不局限于DRPE把它迁移到其他密码系统的参数优化上同样成立。