资讯动态

图像加密中的置乱与扩散:MATLAB实现可逆加解密全解析

发布时间:2026/10/15 6:57:22 来源:尧图企业网站定制
上个月有位师弟A同学找我说他从一篇论文里看到“基于Shuffling和Diffusion的图像加密”框架觉得思路非常简单先打乱像素位置再改变像素值两步就能得到密文图像。但真正落实到MATLAB实现时他却卡住了整整一周——加密图能出解密图却完全无法还原甚至怀疑是自己看错了论文公式。这个场景我再熟悉不过了。图像加密的门槛从来不在“看懂原理”而在于把置乱Shuffling和扩散Diffusion这两个操作在代码层面精确地“可逆”回来。这篇博文我就以这个经典框架为主线把底层逻辑、加解密流程、MATLAB实现和验证指标一次性讲透最后附上可运行的代码和调试心得适合正在做图像加密课题、论文复现或图像隐私保护需求的读者参考。1. 从文本加密到图像加密为什么经典加密算法在这里不够用很多第一次接触图像加密的人都会有同一个疑问AES、RSA这些经典加密算法已经非常成熟为什么还要单独给图像设计一套Shuffling加Diffusion的框架这个问题的答案要从图像数据本身的特殊性说起。1.1 图像数据到底特殊在哪一张灰度图像本质上是一个二维像素矩阵每个像素取值通常在0到255之间。和文本相比它有三个非常鲜明的特点。第一数据量极大。一张1024×1024的灰度图就有超过100万个像素如果按字节算就是1MB。AES分组加密一次只能处理16字节直接对整张图做AES需要至少六万多次分组操作效率并不理想。第二相邻像素之间高度相关。自然图像中左上角像素和右边像素的灰度值通常非常接近甚至完全相同。这种空间冗余是图像能被压缩的根本原因但也意味着如果加密算法不刻意破坏这种相关性攻击者可以通过统计相邻像素关系推断出明文结构。第三像素取值域有限且固定。图像输出要求像素值仍在0到255之间密文必须仍然是一张能显示的图片。AES加密后的字节分布虽然均匀但很难自然映射回图像格式导致密文变成一堆不可视数据这在某些场景下反而会暴露“这里有加密数据”的事实。正是这些特点让传统文本加密在图像领域显得有些水土不服。图像加密更需要的是一套能利用图像结构、同时保留图像格式的专用方案。1.2 传统加密算法在图像上的三个短板我自己实测过把AES应用到图像上的效果问题主要出在三个层面。第一个是块间独立性导致的安全隐患。AES以固定长度分组独立加密如果采用ECB模式相同的明文块会得到相同的密文块。图像里大面积同色区域极多加密后密文中仍然会残留明显的规则纹理根本达不到混淆视觉效果的目的。虽然CBC等模式能解决这个问题但它们本质上是为串行字节流设计的并不关心图像的空间结构。第二个是密钥传播效率低。AES的扩散机制在一个分组内部完成16字节之外的变化无法快速传播。图像攻击者最关心的恰恰是全局统计特性所以传统加密算法对图像这种高冗余数据往往要叠加多轮操作才能勉强打散空间相关性代价是运算量暴涨。第三个是格式不友好。很多实际需求除了“别人看不懂像素内容”还要求密文仍然能作为图片传输、显示或存储。传统算法输出的二进制流无法直接解释成合法的像素值矩阵需要额外封装格式这在实时图像传输场景里非常麻烦。1.3 置乱加扩散图像加密的经典范式早在二十世纪中叶Shannon提出密码设计的两大基本原则混淆confusion和扩散diffusion。在图像加密领域这两个原则被具体化成了两个非常自然的操作。Shuffling也就是置乱对应Shannon理念中的混淆把像素的位置打乱让局部空间结构失效。相邻像素相关性、目标轮廓、纹理走向都在这一步被破坏。Diffusion也就是扩散对应Shannon理念中的扩散把一个像素的微小变化铺开到尽可能多的密文像素上同时改变像素值的统计分布。图像加密的绝大多数算法无论表面怎么包装本质上都在做这两件事。理解了这一点再看任何论文里的流程图基本都能在三分钟内抓住骨架。2. 置乱层让像素位置“乱起来”的底层逻辑置乱是整个加密流程的第一步它的目标非常明确在不改变像素值的前提下把像素的位置彻底打乱。2.1 置乱到底改变了什么假设原始图像是一个3×3矩阵120 121 122 123 124 125 126 127 128置乱后可能变成124 128 121 126 120 125 123 122 127你仔细观察会发现像素值的集合没有变仍然是120到128各出现一次变的只是它们的位置。所以置乱后的图像直方图与明文完全一致。这一点非常重要因为它决定了“只做置乱是不够的”我在后面第3章会详细展开。从数学角度看置乱就是对像素坐标集合做一次映射。如果把图像拉直成行向量p长度Nrows×cols那么置乱就是构造一个1到N的排列order让置乱后的向量满足p[k] p[order[k]]这里的order就是整个置乱层的核心加密时用它正向映射解密时则需要它的逆排列。2.2 基于混沌序列排序的索引置乱构造置乱映射order的方法很多最常见也最容易在MATLAB里实现的是“混沌序列排序法”。思路非常简单先用混沌映射生成一串长度为N的随机序列混沌系统对初值极度敏感所以这串序列看起来就像随机数然后对序列做升序排序排序后的索引就是一个天然的排列。在MATLAB里只需要一条核心语句[~, order] sort(chaosSeq, ascend);这里order的含义是排序后第1个位置对应chaosSeq中最小值所在的原始下标第2个位置对应第二小值的原始下标以此类推。由于chaosSeq的值各不相同order正好是1到N的一个排列可以直接用来置乱。逆置乱时不需要重新排序只需要把order反过来。MATLAB里的写法非常优雅invOrder zeros(size(order)); invOrder(order) 1:numel(order);记住这条公式它是解密能成功的关键。我见过太多人加密时用order解密时也直接用order结果图像只是被打乱了一次再也回不去。2.3 Arnold猫映射与块级置乱除了混沌排序Arnold猫映射也是论文里的常客。它通过对像素坐标做线性变换反复迭代若干次达到置乱效果。数学模型是x (x y) mod rows y (x 2y) mod cols每次迭代等效于把整张图做一个拉伸加取模回绕。Arnold映射有个很有趣的性质迭代到特定轮次会回到原始图像这个周期取决于图像尺寸。但正因为它具有周期性如果密钥空间只包含迭代次数安全性相对有限所以我更建议把它当作置乱的辅助手段而不是唯一方案。还有一类是块级置乱。把图像划分成若干固定大小的小块先打乱块的顺序再在块内部做细粒度置乱。块级置乱的好处是能保留一定局部结构适合对压缩域图像或视频帧做加密同时计算量比全像素置乱低一个量级。缺点则是安全性弱于逐像素置乱因为块内统计特征仍然保留。2.4 只做置乱为什么不够安全置乱虽然让图像看起来“花了”但有几个致命问题。第一直方图不变。攻击者拿到密文图像直接统计像素灰度分布得到的直方图和明文一模一样可以据此推测图像内容比如医学影像中组织区域灰度集中、遥感图像中地物灰度呈多峰分布。第二置乱是纯位置变换像素数值未改变如果明文包含的像素值分布极不均匀比如二值图像置乱后的图像仍能明显看出文字轮廓。第三选择明文攻击风险高。如果攻击者能选择若干已知图像输入加密系统对比明文和密文中哪些像素移动到了哪些位置就有机会还原出置乱映射order。一旦order泄露整个加密就形同虚设。所以置乱必须配合扩散扩散负责“洗掉”像素值的统计特征让密文在直方图层面也安全。3. 扩散层让像素值“完全变样”的关键设计扩散层的作用对象不是像素坐标而是像素值。它的核心目标是改变单个像素的灰度值并让这种改变像多米诺骨牌一样传导到整幅图像。3.1 扩散的核心思想让一个像素影响一片区域如果只是简单地对每个像素做异或加密c[i] p[i] XOR k[i]那么同样像素值仍产生同样密文值图像中大面积相同区域会被加密成完全相同的密文块密文图像上能看出原有轮廓。攻击者也能直接通过统计密文分布反推密钥流。这种“逐点独立”的操作无论密钥流多随机都无法抵御统计攻击和已知明文分析。真正的扩散必须建立像素与像素之间的联系。最直观的做法是引入“前一个密文像素”参与当前像素的加密c[i] p[i] XOR c[i-1] XOR k[i]这就像把每个像素串在一条链条上。明文中的任何一个比特发生变化都会通过c[i-1]这个进位传递下去影响后面所有密文像素。这种链式结构就是图像扩散最经典的实现方式也经常被叫作“像素间扩散链”。3.2 前向扩散链的数学表达我把正向扩散定义写成下面这样其中c[0]可以取0作为初始进位c[i] p[i] XOR c[i-1] XOR k[i] (i 1, 2, ..., N)解密时只需要从第1个像素开始逐步逆推p[i] c[i] XOR c[i-1] XOR k[i] (i 1, 2, ..., N)注意解密公式里利用的是XOR的自反性。由于c[i-1]在解密时已经知道所以这个逆运算不需要依赖任何未知信息。关键在于顺序必须严格保持一致加密从前往后扫解密也必须从前往后扫因为c[i-1]总是在前面。有的同学问为什么往往还要再做一轮从后往前的扩散这是为了让每个像素同时受前后两个方向的像素影响雪崩效应更均匀。单向扩散虽然也能传播变化但最开头的像素只受初始进位影响敏感度偏低。双向扩散的做法是第一次从后往前扩散第二次从前往后扩散解密时反过来先逆正向再逆反向。实现逻辑不变只是多跑一遍循环。3.3 模加与异或的选择扩散操作不一定非用XOR理论文章里常见两种XOR运算。速度快MATLAB直接支持uint8类型按位异或可逆性好硬件实现简单。模加运算形如c[i] mod(p[i] c[i-1] k[i], 256)。解密时用模减效果类似但非线性特征略有不同。两种都可以用实战中我更推荐以XOR为主、模加为辅的组合。因为XOR在传播比特变化时非常均匀而模加在加法溢出时会丢失高位信息虽然密码学上未必是缺陷但对初学调试来说XOR的逆运算心智负担更低。如果想提高非线性度可以这样混合c[i] bitxor(mod(p[i] c[i-1], 256), k[i]);这样即使密钥流被部分泄露攻击者还原明文也要同时处理异或和模加两层操作。代价只是多一次mod性能影响几乎可以忽略。4. 加解密主流程密钥调度与可逆性设计把置乱和扩散叠到一起就构成了完整的图像加密框架。但顺序怎么安排、密钥怎么生成、解密怎么逆回去这些细节决定了整个系统能不能用。4.1 混沌映射与密钥流的生成我平时最常用的混沌映射是Logistic映射x[n1] mu * x[n] * (1 - x[n])当参数mu在3.57到4之间、初值x[0]在(0,1)内时序列会进入混沌状态表现为非周期、对初值极端敏感。只需要两个小数字x[0]和mu就能生成整个加密所需的全部随机序列。用Logistic映射生成密钥流时我有两个习惯第一丢弃序列开头的若干项。因为混沌映射从初值出发后需要一段过渡才能充分进入混沌状态直接使用开头几百项会带来可预测性风险。一般丢弃前1000项代价极小但安全性提升明显。第二用不同的“种子偏移”区分置乱序列和扩散序列。置乱用原始x[0]扩散用x[0]0.001这样两条序列互不相关又不需要额外保存密钥。扩散序列转换成像素密钥流时取小数后6位再取模256keyStream uint8(mod(floor(seq * 1e6), 256));这一步的目的是把连续混沌值映射到0到255的离散像素值域同时保留足够精度。4.2 加密与解密流程的对称性整个加密流程可以总结为四步明文图像 - 1. 拉直为像素向量p - 2. 利用混沌序列排序生成order - 3. 置乱p1 p(order) - 4. 扩散c[i] bitxor(bitxor(p1[i], k[i]), c[i-1]) - 密文图像c对应的解密流程必须严格反向密文图像c - 1. 逆扩散p1[i] bitxor(bitxor(c[i], k[i]), c[i-1]) - 2. 逆置乱p[order[k]] p1[k]或者构造invOrder后p p1(invOrder) - 3. 恢复二维矩阵 - 明文图像很多初学者把“加密先置乱再扩散”误解成“解密先逆置乱再逆扩散”这个顺序一旦搞反解密结果无论如何都对不上。正确思路是解密是加密的逆过程后发生的操作先被撤销所以解密必须先逆扩散再逆置乱。4.3 彩色图像的三通道处理策略如果待加密对象是彩色RGB图像处理方式有两种。第一种是通道独立加密。分别对R、G、B三个通道各自做置乱和扩散实现最简单但存在明显隐患同一物体在三个通道上的值通常高度相关独立加密后三个密文通道之间仍然保留这种相关性攻击者可以把三通道叠起来观察。第二种是我比较推荐的做法把三个通道的像素拼接成一个长向量用同一套置乱索引order打乱整个向量的位置但用不同偏移的密钥流分别扩散三个通道。这样既实现了“跨通道混合”让R通道的像素可能移动到G通道的位置又保证了密钥流之间相互独立。实现时只需要在reshape之前把三通道按顺序纵向堆叠vec [img(:,:,1)(:); img(:,:,2)(:); img(:,:,3)(:)];处理完再切回三段分别reshape回对应通道即可。5. MATLAB实现拆解可直接运行的核心代码下面给出我调试通过的MATLAB实现。为了阅读方便我按功能拆成四个函数最后给一个完整调用示例。这些代码直接复制就能跑前提是输入图像为uint8灰度图。5.1 混沌序列生成函数function seq logisticSeq(x0, mu, n, burnIn) %LOGISTICSEQ 生成Logistic混沌序列 % 输入: % x0 - 混沌初值, (0,1) % mu - 控制参数, (3.57, 4] % n - 需要生成的序列长度 % burnIn- 丢弃的前缀长度, 默认1000 if nargin 4 burnIn 1000; end seq zeros(1, n, double); x x0; for i 1:(burnIn n) x mu * x * (1 - x); if i burnIn seq(i - burnIn) x; end end end注意保存密钥时务必保存足够位数的x0和mu推荐至少保存double类型的完整精度。否则浮点数四舍五入到小数点后4位解密时会得到完全不同混沌序列图像还原直接失败。5.2 置乱与逆置乱函数function shuffledVec permuteByIndex(vec, order) %PERMUTEBYINDEX 根据order对向量置乱 % 新向量的第k个元素 原向量的第order(k)个元素 shuffledVec vec(order); end function restoredVec inversePermuteByIndex(shuffledVec, order) %INVERSEPERMUTEBYINDEX 根据order逆置乱 invOrder zeros(size(order)); invOrder(order) 1:numel(order); restoredVec shuffledVec(invOrder); end这里的invOrder构造几乎是所有置乱实现的标准做法。如果你手头有现成的排序结果order逆排列不需要再排序一次一条赋值语句就能搞定。5.3 扩散与逆扩散函数function cVec forwardDiffusion(pVec, keyStream) %FORWARDDIFFUSION 前向链式扩散 n numel(pVec); cVec zeros(size(pVec), uint8); carry 0; % 初始进位c[0] for i 1:n cVec(i) bitxor(bitxor(pVec(i), carry), keyStream(i)); carry cVec(i); end end function pVec inverseDiffusion(cVec, keyStream) %INVERSEDIFFUSION 前向链式逆扩散 n numel(cVec); pVec zeros(size(cVec), uint8); carry 0; for i 1:n pVec(i) bitxor(bitxor(cVec(i), carry), keyStream(i)); carry cVec(i); % 注意: 这里进位是密文, 不是明文 end end这段代码里的反直觉细节在“carry cVec(i)”这一步。解密时当前轮的进位必须保存当前密文像素而不是刚解密出来的明文像素因为加密时下一轮依赖的是密文值不是明文值。这是初学者最容易搞错的地方之一。5.4 加解密主流程与调用示例function cipherImg imageShuffleDiffuseEncrypt(plainImg, x0, mu) %IMAGESHUFFLEDIFFUSEENCRYPT 图像加密主函数 % 输入plainImg必须为uint8二维灰度图 [rows, cols] size(plainImg); N rows * cols; pVec plainImg(:); % 1. 生成置乱索引 seqShuffle logisticSeq(x0, mu, N, 1000); [~, order] sort(seqShuffle, ascend); % 2. 置乱 shuffledVec permuteByIndex(pVec, order); % 3. 生成扩散密钥流并扩散 seqDiffuse logisticSeq(x0 0.001, mu, N, 1000); keyStream uint8(mod(floor(seqDiffuse * 1e6), 256)); cVec forwardDiffusion(shuffledVec, keyStream); % 4. 恢复二维图像 cipherImg reshape(cVec, rows, cols); end function plainImg imageShuffleDiffuseDecrypt(cipherImg, x0, mu) %IMAGESHUFFLEDIFFUSEDECRYPT 图像解密主函数 [rows, cols] size(cipherImg); N rows * cols; cVec cipherImg(:); % 1. 生成与加密完全相同的扩散密钥流并逆扩散 seqDiffuse logisticSeq(x0 0.001, mu, N, 1000); keyStream uint8(mod(floor(seqDiffuse * 1e6), 256)); pVecShuffled inverseDiffusion(cVec, keyStream); % 2. 生成与加密完全相同的置乱索引并逆置乱 seqShuffle logisticSeq(x0, mu, N, 1000); [~, order] sort(seqShuffle, ascend); pVec inversePermuteByIndex(pVecShuffled, order); % 3. 恢复二维图像 plainImg reshape(pVec, rows, cols); end调用测试% 读取测试图像并转为灰度 img imread(cameraman.tif); img im2uint8(img); % 确保uint8 % 密钥 x0 0.314159265358979; mu 3.999; % 加密与解密 cipherImg imageShuffleDiffuseEncrypt(img, x0, mu); decryptedImg imageShuffleDiffuseDecrypt(cipherImg, x0, mu); % 验证: 最大绝对误差应为0 maxDiff max(abs(double(img(:)) - double(decryptedImg(:)))); fprintf(最大像素误差: %d\n, maxDiff); % 显示结果 subplot(1,3,1); imshow(img); title(明文图像); subplot(1,3,2); imshow(cipherImg); title(密文图像); subplot(1,3,3); imshow(decryptedImg); title(解密图像);如果maxDiff输出为0说明可逆性设计完全正确。如果输出不为0先检查密钥是否一致再看逆扩散里的carry保存的是不是密文。6. 安全性验证直方图、相关性、熵、NPCR与密钥灵敏度图像加密做得好不好不能只靠肉眼觉得“密文图一团乱麻”。我一般会跑一组客观指标把结果写成表格既证明算法有效也能在论文里直接引用。6.1 视觉层面的直观判断第一步永远是直接看密文图像。合格的密文图像应该完全看不出原图的轮廓、边缘和纹理。注意有一种常见误判当图像整体偏暗时密文也可能看起来偏暗这不等于安全。必须结合直方图判断不能只看“感觉”。6.2 直方图与信息熵好的加密算法会让密文图像像素值分布接近均匀。理论上8位灰度图像的理想信息熵是8.0000实际密文图像熵值如果能到7.990以上说明扩散层已经把像素概率分布洗得很均匀了。信息熵的计算公式是H -sum( p(i) * log2(p(i)) )其中p(i)是灰度值i出现的频率。MATLAB实现function h imageEntropy(img) counts imhist(img, 256); prob counts / numel(img); prob prob(prob 0); h -sum(prob .* log2(prob)); end如果明文直方图有尖峰而密文直方图趋于平坦扩散层就算合格了。6.3 相邻像素相关性测试自然图像的一个重要特征是相邻像素高度相关水平方向相关系数经常超过0.9。置乱层的作用就是把这个系数压到接近0。我通常分别计算水平、垂直、对角三个方向的相关性。计算公式r sum((a - mean(a)) .* (b - mean(b))) / (sqrt(sum((a - mean(a)).^2)) * sqrt(sum((b - mean(b)).^2)))MATLAB里可以直接用corrcoef简化function r adjacentCorrelation(img, direction) switch direction case h a img(:, 1:end-1); b img(:, 2:end); case v a img(1:end-1, :); b img(2:end, :); otherwise a img(1:end-1, 1:end-1); b img(2:end, 2:end); end a double(a(:)); b double(b(:)); tmp corrcoef(a, b); r tmp(1, 2); end合格的密文图像三个方向相关系数绝对值一般都应小于0.1越接近0越好。注意明文相关性往往三个方向都很高如果密文某个方向仍然显著相关说明置乱映射不够理想需要检查order生成的随机性。6.4 NPCR与UACI抵御差分攻击的能力NPCR衡量的是“明文中改变一个像素密文有多少比例的像素发生变化”。UACI衡量的是“变化像素的平均变化强度”。这两个指标专门验证算法能否抵抗差分攻击也就是攻击者通过构造微小篡改来分析密文差异的技巧。NPCR计算公式NPCR mean(D) * 100%其中D(i,j) 1如果c1(i,j) ≠ c2(i,j)否则为0。8位灰度图像的理想判定阈值约99.6094%。UACI计算公式UACI mean(|c1 - c2| / 255) * 100%理想参考值约33.4635%。具体做法是加密原始图像得c1随机选定一个像素修改其灰度值比如加1再加密得c2比较c1和c2计算两个指标。我的经验是用代码里的扩散链结构去测NPCR时只要修改位置不是最后一个像素NPCR基本都能达到99.6%以上。因为链式扩散保证了单像素变化从该位置向后传播到整幅图但注意最后一个像素之后没有后续像素如果修改的是最后一个像素变化不会向后传播测试时会偏低。很多论文里的NPCR值偏低往往就是随机采样点落在图像末尾附近导致测试时要做好边界处理。6.5 密钥灵敏度测试混沌加密的一大卖点是密钥极其敏感。x0差1e-15解密结果就应该完全“面目全非”。测试方法很简单用x0加密用x01e-15解密计算解密图像与明文图像的平均绝对误差或MSE。一个合格的混沌图像加密系统微小密钥偏差解密出的图像应该接近随机噪声MSE应在数千量级。如果密钥差1e-3才能破坏解密说明系统对密钥的敏感度不够存在字典攻击风险。我一般还会做一个更直观的测试分别用两个只有细微差异的密钥解同一张密文图把两张解密结果相减后显示。如果差异区域呈雪花状均匀分布说明扩散充分如果差异集中在某个角落说明扩散链没有把密钥差异均匀传导到全图。7. 初学图像加密最容易翻车的几个坑最后把我在代码调试和帮同学看代码过程中遇到的典型问题集中列一下。这些问题本身不大但每一个都能让人卡很久。7.1 排序索引映射方向搞反这是置乱实现中的头号问题。order作为排序索引既可能被解释成“旧位置到新位置”也可能被解释成“新位置取旧位置的哪个像素”。两种解释都行但逆置乱必须严格对应。我的建议是死记这一条加密时用p(order)取像素解密时把invOrder(order) 1:N之后再用p(invOrder)取像素。无论你怎么理解都先用一条一行的小图像做往返测试再放真实图像。7.2 逆扩散时把进位混成明文逆扩散里的carry必须保存密文序列的当前值而不是刚解出的明文值。我见过最典型的错误是这样% 错误示范 carry pVec(i); % 错! 加密时下一轮依赖的是c[i], 不是p[i]解密时把这一行改成carry cVec(i)问题马上消失。调试时建议先不接置乱单独验证扩散往返是否无损能快速定位错误发生在哪一层。7.3 浮点精度导致密钥不一致MATLAB默认double精度很高但有些同学习惯把密钥保存成4位小数比如x00.3141。加密用0.314159解密用0.3141看似差不多混沌序列却会迅速分叉导致完全无法解密。密钥要么直接用原变量保存到.mat文件要么在程序里统一使用完整精度常量。7.4 密钥空间设计过小如果只把x0当作密钥mu固定为3.99密钥空间来自x0的浮点精度虽然数值上不小但实际可用的有效范围有限。更稳妥的做法是把x0和mu同时作为密钥必要时再加上置乱位数、Arnold迭代次数、分组大小等参数共同组成复合密钥。攻击者即使猜到部分整体破解难度也会大幅上升。7.5 忽略瞬态效应直接用序列开头Logistic映射从初值出发后前几百项往往受初值影响较大且轨道的“随机性”需要一段过渡才稳定。我调试时对比过不丢弃前1000项直接生成密钥流在某些初值组合下密文图像的直方图会出现微弱周期痕迹。虽然绝大多数时候不影响解密但从安全角度保留burn-in环节更稳妥。7.6 彩色图像通道独立加密遗漏通道相关性前面提过R、G、B三个通道独立加密会让通道间的相关性残留。如果只是演示算法通道独立可能够用如果是要写论文或做真实保护建议至少把三个通道的像素拼接后再做一次跨通道置乱否则攻击者可以利用通道相关性做联合分析。7.7 测试NPCR时边界越界调整明文像素做NPCR测试时如果随机坐标已经位于图像最后一个像素单向扩散链的变化传播会被截断结果不达标。更合理的方式是随机选取至少50个位置分别测试去掉末尾附近的点位或者干脆把正向扩散之后再加一轮反向扩散让最后位置也能受后续虚拟进位影响。如果刚才这一堆验证指标和踩坑点都跑通了你的置乱加扩散加密框架基本就可以放心用于实验对比或论文插图了。我自己现在做图像加密课题仍然会先用这个最小框架验证新思路再往里面叠加更复杂的变换。说实话图像加密的算法层可以很花哨但无论加多少层处理最终都逃不过“置乱破坏位置相关性、扩散破坏像素统计特征、解密严格逆序”这三件事。把这三点刻在脑子里任何一篇这个领域的论文你都能很快拆解成可复现的代码。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑