关于非常间谍身份验证方法

因此,我们将超级特工爱丽丝(Alice)和鲍勃(Bob)送到一个秘密国家的秘密基地。 在执行任务期间,他们将必须联系并一起工作,交换信息,进行日常间谍活动。 当然,所有这些都必须遵守所有可能的规则和安全程序。


的确,在最后一轮,我们想向他们透露:特派团本身和特工本身以及所有国家安全都处于危险之中。 因此,向间谍提供最少的必要信息符合我们的利益。 特别是,他们对彼此和通信技术的了解越少越好。


但是,他们将如何确定其总部战友?


KDPV


TL; DR-为不存在的国家的虚构的三个字符的机构发明了使用隐写术的用户身份验证机制。


关于狼和羊皮


封面是封面,所以爱丽丝和鲍勃都不应该因其任何行为引起怀疑。 适当的计划意味着对在所有可能的水平上对其进行持续监视的偏执狂。 这篇文章不会解决直接交换信息的任务(它应该拥有自己的单独系列),而仅仅是确保信息被需要的人传递给需要的人的一种方式。


而且,两个间谍极有可能以普通公民的身份拥有历史,而且彼此之间毫无联系。 因此,您必须立即否决使用传统的加密工具和安全通道-每个反情报代理都知道,没有亲密关系的诚实人没有什么可隐瞒的。


怎么办


当然,这样的任务并不是新任务,它很高兴地存在并且早在您的Internet出现之前就已解决。 而且不仅做出了决定,所以一些决定在文化上得到了加强,并且仍然存在于书籍,电影和游戏中。


让我们看一个这样的场景:两个穿着大衣的人在一个公共场所会聚,交换非常奇怪的短语。 如果发起的短语和答案正确,则身份验证成功,并且人们交换标记为“最高机密”的文件夹,并在未知的方向分散。


这种方案的缺点很明显-短语必须保密并且经常更改 ,这在敌方领土上并不是很简单。 同时,为了不被偶然发声并且不引出KDPV的情况,它们变得相当突出和随机,这意味着他们可以发出发声者。



在数字技术时代,我们不喜欢这种方法。 尤其是当您回想起几乎所有的沟通渠道都是由某人控制的时,无论动机是好是坏。 而且,无论他们向我们保证什么,人们的生活都不应受到任何Facebook隐私政策的信任。



隐写术(再次?)


刺猬很明显,在这种情况下彼此隐藏能力比以往任何时候都更具吸引力。 实际上,即使所描述的方法是其亚种-代码短语也可以视为内部仅包含一点信息的容器。


食虫动物科的同一哺乳动物了解到,这并不是简单地将隐蔽容器互相扔。 与某些普通的PGP加密相比,这种交换将引起几乎更多的怀疑,因此我们不感兴趣。


那怎么办


与密码不同,隐秘容器具有明显的优势-应用程序上下文。 除了明显的内容以外,任何文本,图像,音频文件等也都具有进行自然讨论的可能性,不仅可以从海湾发送,而且可以在不引起怀疑的对话过程中发送。


有了这样的想法,我们就可以基于公共密钥草拟一个简单的隐写身份验证协议:


  • A-> B:一条漂亮的消息,要求隐匿某些参数的容器;
  • B:选择与请求的上下文和参数匹配的容器C
  • B:类似地创建消息M
  • B-> A: C'=嵌入(C,M,K)
  • A:检查C'是否符合设置的参数;
  • A-> B: M'=提取(C',K)
  • B:检查MM'是否匹配。

这样的协议有明显的缺点-Alice和Bob必须同时具有公用密钥以及嵌入和提取功能。 他们的妥协可能导致对敌人的身份验证方法进行详细分析的可能性,并危及其他用户和总部。 需要修复某些问题。


艺术家不是臭虫


如果读者在计算机课问世之后上学,那么他应该记得使用乌龟,蚂蚁等表演者学习算法的基础知识。 他们的想法是演示通过创建简单程序来优化大量手动单项操作的可能性。 为了解决我们的问题,我们需要朝相反的方向发展。


好吧,不是很可爱吗?


由于我们可以根据给定的参数简化最终算法的编写过程,从步骤序列到过程描述,因此我们可以执行逆过程。 如果您将容器想象成是其某些组件的数组,那么按键嵌入消息可以写为在容器元素上具有各种常数参数的特定索引处的有序操作序列。


这是非数学开始的地方,所以我请胆小的人简单地将难看的段落翻到运算部分,甚至更进一步。 我保证,没有可怕的事情会发生。


要嵌入数据,我们需要以下形式的序列: (f1,S1,i,D1),(f2,S2,j,D2)... ,其中:


  • Di-嵌入式数据的某些部分;
  • i,j是容器元素的索引;
  • fi:(状态,元素,D)->(状态,元素) -嵌入函数;
  • Si是操作的上下文, (El',S [i + 1])= fi(Si,El,Di)

要提取它,您不需要存储部分数据(K.O.),因此有足够的三元组: (g1,S1,I1),(g2,S2,I2)...具有相同的值,只有gi:(State,Element)-> (状态D)


所有这些可以通过下面的对称图表示。 如果由于某种原因我未能弄清楚,那就不吓人了,请继续阅读。


好还是没有


可以看出,嵌入功能具有更大的自由度。 与她的姐姐不同,她修改了容器,同时基于两个独立的元素(嵌入式数据和元素)进行了修改。 谢谢,或更确切地说,正因为如此,通过这种系统实现隐写算法的两种全局方法是可行的:


  1. 选择最合适的元素索引以根据嵌入功能进行更改(最不明显或根本不需要),然后将形成的序列绑定到特定容器。 使用这种方法,在需要使用诸如加密和其他安全媒体之类的经典方法进行嵌入之前,需要将它们彼此隔离。
  2. 找到一种将容器划分为元素和嵌入函数的方法,以使容器进行的任何预期更改都将同样不可见。 在这种情况下,序列与容器无关,甚至可以由完全随机的生成器创建。 灵活性降低,最坏情况无法控制。 另一方面,这种方法在现场应用时更简单,更方便,因此下面我将使用它。

如果算法不需要状态,则以上所有内容仍然有效,只是在图中没有单个字母和块。 实际上,没有它,它甚至更加容易。


为什么我们需要它?


现在,如果您预先知道将使用哪个容器来使用消息和密钥,而不是完全公开算法的各个部分,则可以生成并提供仅用于相似序列的代理,并为其提供解释器。 好吧,当然,不仅仅是奉献,以后还会更多。


添加不对称


即使是乌龟艺术家也可以通过数百种不同的方式绘制正方形,只需更改操作顺序并添加新的操作即可。 这意味着没有人会打扰我们,并且不会对固定输入数据的描述序列做同样的事情。


也就是说,我们可以采用嵌入顺序,添加新操作,将其全部混合,以使结果保持不变。 除非存在状态,否则将有必要对其进行跟踪并为序列单独添加必要的更改。 这就是为什么没有它会更容易,是的。


经过这样的揉捏和嘈杂,一种或另一种方式,甚至嵌入者本人也将不再能够理解他实际嵌入的内容: N个操作的任何序列都将代表N! 潜在的嵌入消息-嵌入部分的每个排列对应一个。 同时, N本身是一个大问题。 因此,可以将这样的序列称为开放-它们既不提供有关嵌入消息的信息,也不提供有关所使用的算法和密钥的任何信息。


在提取信息时,对于我们(从所有可能的位置恢复相同的正确消息)和要提取的部分数量这两个方面都非常重要,因此提取顺序从诞生之日起就保持不变。 由于它们隐式包含有关所使用的密钥,生成器和算法的信息,因此像红皮书中的动物一样,需要对其进行存储和保护。 并保密。


不对称与它有什么关系? 事实是,现在每个提取序列都与无限数量的嵌入器相关联。 在通常情况下,一个与另一个的还原是一项艰巨的任务。


我们正在经营


我们忘记了任何近乎数学的知识,回到原来的任务-我们如何将爱丽丝和鲍勃送到敌方领土,以便:


  • 他们不认识对方的脸
  • 手头没有秘密算法
  • 但是您可以在开放频道上进行交流时互相验证吗?

好吧,在第一段中,所有内容都很清楚,我们只是不向他们提供彼此的任何明确信息,也没有共享密钥。 第二,您需要记住上面协议的描述。 现在,我们可以直接排除代表潜在状态机密和所有这些内容的EmbedExtract算法。 并且,考虑到这一点,对于第三个协议,可以制定以下两阶段协议。


在任务开始之前生成身份验证信息,总部是Trent的可信任方:


  • T:选择密钥算法和密钥K,并在其帮助下创建:
    • 提取序列Ex ;
    • 适用于身份验证(在下面)的Ctx上下文;
  • T-> A: Ctx,Ex
  • T:使用Ex和创建的上下文,生成:
    • 消息M先前未用于零件中的所选代理| Ex | ;
    • Em的一次性序列,如上所述将其打开;
  • T-> B: Em,h(M) (如果需要)创建其他集合。

因此,爱丽丝在所有场合和未来联系的上下文中只有一个序列,而鲍勃成为其中嵌入的一组一次性序列和消息哈希的快乐所有者。


任务期间已经存在的身份验证协议如下所示:


  • A-> B:基于Ctx上下文并带有容器描述的启动IM消息;
  • B:选择合适的C〜IM
  • B-> A: C'= Em(C)
  • 答:检查是否符合C'〜IM (由于更改是不可见的,因此应将其保存);
  • A-> B: M'= Ex(C') ,标记为M'。
  • B:检查, h(M')== h(M) ,破坏Em,h(M)

细心的读者会注意到,在协议之前,爱丽丝和鲍勃只有一套信息,这本身对他们或潜在的对手都没有任何意义,仅在“玩弄颜色”期间。


每个开放的Bob集仅使用一次,这由Alice的倒数第二步控制。 当遇到另一个人以前使用过的M (因此她看不见Em )时,她意识到自己的一个“同伴”是假货。


同一个人的反复使用告诉她,她不了解协议的复杂性,而且肯定不是与她联系的人。 好吧,迟到总比没有好。



好的,这就是所有看起来太复杂和不可理解的地方。 有人来过吗?


让我们更好地在实践中进行演示,因为即使是间谍本身也不需要知道使用协议的细节,更不用说贫穷的读者了。 刚开始的时候,它只是关于如何实现的。


高科技


因此,仅需编写该协议所需的所有内容。 好吧,尽管您可以做到,但您并不能做任何事情。 今天,我的代码的受害者将是…… 命运之轮 ……Java? 好吧,好吧,与此同时,STL中的所有功能都将成为现实,您无需寻找任何东西。


让我们从所需的API开始。 要工作,只需要确定容器元素数组的类即可通过索引接收和更改元素:


class MyContainer implements StegoContainer<MyElement> { public MyElement get(int i) { //  i-  } public void set(int i, MyElement v) { //  i-  } public int size() { //    } } 

减少了进一步的使用,以在必要的容器上创建隐写自动机的包装,并将嵌入和提取的功能提供给其输入:


 StegoMachine<MyState, MyElement> myMachine = new StegoMachine( initialState, new MyContainer<MyElement>(/*   */) ); final StegoEmbed myEmbed = (st, el, dp) -> { //    dp   el   st }; final StegoExtract myExtract = (st, el) -> { //     el   st return dp; }; //    MyDataPart part = /*    */; myMachine.exec(1337, myEmbed, part); //... //    /,   //      State currState = myMachine.getState(); //... //    part = myMachine.exec(80085, myExtract); //... //        MyContainer container = (MyContainer) myMachine.getContainer(); 

如果算法的实现不需要维护内部状态,则以相同的方式使用带有后缀Stateless的类。


序列生成器可以根据需要工作,并且没有通用的API。 在一般情况下,任何东西一般都可以成为数据的一部分,从单独的位到单独的编码中的摇滚艺术品。


实施实例


关于方法


作为实现的示例,使用创建的接口,我实现了LSB系列的一种简单算法,用于具有无损压缩的位图图像。 它们的元素是在所有RGB分量的最低有效位中没有邻居的像素。 embed函数与源数据的单个位一起使用,并且仅更改组件之一(索引将指向)的值的低位。


这很简单,但是对于实现协议非常有用,因为根据他们的选择改变任何元素同样是不可察觉的,因此要更改的元素的索引是使用随机生成器生成的。 对于Java,使用SecureRandom ,但是如果需要的话,它很容易更改为其熵源。


不过,这是一种非常简单的方法,我不建议将其用于真实间谍。


关于哈希


由于文本趋向于根据代理的模拟身份而失真(有些不放大写字母,另一些不喜欢放表情符号等,其他通常不识字),因此我建议使用sha256来计算哈希值,但只能使用小写的印刷单词:


 h("Hello world?...") == h("hello, world!11") 

关于界面


该软件包包括两个部分-一个部分用于生成序列,其他用于Trent的哈希,另一部分用于嵌入和检查收到的消息是否符合要求。


两者的工作都从命令行通过其参数和输入输出流进行;没有其他接口被交付(恐惧和恐惧)。 仍然,作为总部的雇员,间谍-意味着具有某种资格。 好吧,如果没有,我仍然会举一个例子。


这是一个帮助

用法截图



他们都做什么?


首先,总部的Trent需要制定身份验证信息。 特别是要事先考虑代理将工作的情况。


例如,假设Bob是图形自由职业者,而Alice是他的客户。 身份验证将以创建图形/设计/其他东西的命令为幌子进行。


我们向双方报告此有用信息,并返回到协议本身。 我们将预先准备合适的M.txt嵌入式消息,以减少其中的字符数:“它非常适合在我汇款的地方。” 使用Trent实用程序生成EmEx


 Trent@HQWorkstation:~$ java -jar HQUtil.jar -ex $(stat -c%s "M.txt") 4096 > Ex.txt Trent@HQWorkstation:~$ cat Ex.txt | java -jar HQUtil.jar -em "$(cat M.txt)" 0.25 4096 > Em.txt Trent@HQWorkstation:~$ cat M.txt | java -jar HQUtil.jar -h > hash.bin 

$(stat -c%s "M.txt")返回消息的大小(以字节为单位),以及$(stat -c%s "M.txt")所生成索引范围的限制(以允许使用较小的容器)。 同样, $(cat M.txt)用于将消息本身传递给命令行参数。 原则上,您可以使用自己的体力劳动来避免重击,但是对谁来说更方便。


Ex.txt传递给Alice, Em.txthash.bin传递给Bob。 现在,假设代理已成功部署并希望彼此通信-我们继续执行协议。 鲍勃将自己的简历或工作机会交换出去,爱丽丝开始交流:


 : ,     %_% :        ,   .  ? : ,    

鲍勃寻找一把雨伞的图像,如果灵魂有创造力,甚至可以自己绘制一把雨伞,或者稍加压缩/施加水印(或者自由职业者现在在那做的事情),然后执行以下操作:


 Bob@PC:~$ cat Em.txt | java -jar SpyUtil.jar -e umbrella.png 

等待一会儿,假装上班,如果实际上他没有做,他自然会考虑上下文,将已收到的容器发送给Alice:


 : ,  ,      

传送带信息的雨伞,670kb


依次检索内部存储的消息:


 Alice@PC:~$ cat Ex.txt | java -jar SpyUtil.jar -e umbrella.png       

将一组单词转换为普通句子并将其发送给Bob:


 : ,  ,   ? 

他检查消息的准确性:


 Bob@PC:~$ java -jar SpyUtil.jar -c hash.bin ",  ,   ?" ,  ,   ? - Correct 

如果一切正常,并继续进行轻松的交流。 观察者的整个对话看起来像这样:


500 KB gif


显然,在所有这些拦截中,反情报都不会发现任何可疑的东西。 实际上,在这种情况下,甚至隐身分析方法也不会总是被应用-好吧,有人以5美元的价格订购了一把雨伞的照片,他们发现了一些令互联网感到惊讶的东西。 计算资源和人员并非无休止地检查每种情况。 认证成功,大幕。


-> github

Source: https://habr.com/ru/post/zh-CN456670/


All Articles