strobe——面向IoT物联网应用的密码学协议框架

Deadly 提交于 2019-12-07 11:56:28

1. What is strobe?

strobe为面向IoT物联网密码学协议框架,使其在小的IoT设备上更易于开发、部署和分析。strobe适于在16位或32位的微处理器上运行。

strobe同时也是一种轻量级的网络协议,可作为TLS的替换。因为对于资源有限的IoT设备来说,可能无法运行TLS协议。

strobe基于SHA-3 KECCAK-f函数来进行消息的加密和认证。

目前有NACL, Noise, BLINKER等多种协议框架,strobe跟BLINKER是同一家族的。
目前的现状为:

由此可知,主要考虑noise和strobe两个协议。
2017年,Facebook工程师有博客专门讨论Noise+Strobe=Disco,对noise(非对称加密)和strobe(对称加密)做了对比,并用go语言做了一个实现,代码仓库为:https://github.com/mimoo/disco ,该仓库至今仍较活跃。

2. KECCAK-f

2012年10月,美国NIST选择了Keccak算法作为SHA-3的标准算法,Keccak拥有良好的加密性能以及抗解密能力。
Keccak算法已经作为面向移动通信(TUAK)3GPP TS 35.231的标准,以及NIST FIPS 202SP 800-185中的标准,经过了大量公开的密码学审查和第三方密码学分析。

KECCAK-f主要有KECCAK-f[25]、KECCAK-f[50]、KECCAK-f[100]、KECCAK-f[200]、KECCAK-f[400]、KECCAK-f[800]、KECCAK-f[1600]这几种。
在这里插入图片描述
Keccak[r, c]与KECCAK-f的关系为:f=r+c
Keccak的一些实例标准有:
在这里插入图片描述

3. strobe的作用

在这里插入图片描述
在这里插入图片描述

4. strobe的设计思想

论文《The Strobe protocol framework》中指出,strobe的主要设计原则为:在任意阶段的密码学输出,除依赖于密钥外,还依赖于之前所有的输入。比如,加密一个消息,所生成的密文除依赖于key和明文外,还依赖于之前的数据如nonces和关联数据等。为实现该设计原则,strobe一直在keep a running hash of the protocol transcript。

strobe的该设计原则更侧重于简单和安全,而不是速度。

因为有running hash的缘故,strobe特别适于保证在传输层消息的有序传输的可靠性;strobe也适于半双工模式,即双方依次发送消息而不是同时发送。如TLS安全传输协议在握手阶段采用的就是半双工模式,当信道打开后才是全双工模式。在握手阶段,通常需要两个不同的密钥key,一个用于从Alice给Bob发消息,另一个用于从Bob给Alice发消息。

strobe主要承担协议中的对称加密部分,公钥加密和签名等仍需要借助其它密码学原型,如RSA或椭圆曲线等。

4.1 strobe的oprations

strobe框架主要位于两个领域:

  • 应用层:应用层有直接使用的数据,如密钥、铭文消息、nonces随机数和关联数据。需要保护这些数据的隐私和完整。
  • 传输层:主要有各方传输的数据,以及需要存储或从不可信内存恢复的数据。这些数据包括密文,传输中的可读消息,MACs和签名。

应用层不直接操作传输层,应用层读写数据均借助strobe的加解密操作。
在这里插入图片描述
在上述图中,做了一个假设,即传输层不可信,而应用层是可信的。

通过strobe交互的信息可分为四大类:
在这里插入图片描述
在这里插入图片描述
上图中的:

  • RATCHET既没有输入也没有输出,用于防止回滚攻击。RATCHET通常会清理掉部分状态,当设备太小无法运行memory-hard函数时,可通过由密码生成密钥来实现相同的功能。
  • KEYAD操作具有相同的数据刘翔,两者均是对随机预言机的输入。KEY操作会用新key重写overwrite部分状态,所以只要新key一直存在,就可像RATCHET一样防止回滚。strobe仅在新block开始时才会有重写操作,所以KEY操作比AD更安规。non-sponge framework非海绵框架如Noise协议,也会做key和associated data的区分。strobe做该区分有利于其与其它协议的对接移植。

(I,A,C,T)为4个bit位,实际执行时采用的是一整个byte,共8个bit位。剩余的4个bit位中有一个表示为M,用于区分metadata,对I/A/C/T等操作无影响,仅用于hashed into the protocol transcript;有一个表示为K,作为DPA-resistant \key tree" extension,对I/A/C/T等操作有影响;剩余的2个bit作为保留位,目前暂未使用。

4.2 strobe的protocol transcripts

strobe一直在维护 a running hash of the protocol transcript,实际即为从应用层看到的一序列所有的操作和数据。其中的操作包含KEYAD等不给传输层数据的操作。

protocol transcript为一系列组合对:
(AdjDir(I0;operation),AppData)(AdjDir(I_0;operation),AppData)
(AdjDir(I0;.)(AdjDir(I_0;.)函数可adjusts the operations so that when Alice sends a message (with I=0I=0) and Bob receives it (with I=1I=1), the two protocol transcripts will match.
AdjDir(I0,(I,A,C,T,M,K)):=(I(TI0),A,C,T,M,K)AdjDir(I_0,(I,A,C,T,M,K)):=(I\oplus (T\cdot I_0), A,C,T,M,K)
where I0I_0 is the value of the II flag in the first operstion that has T=1T=1.也就是说,对于发起者来说I0=0I_0=0,对于接收者来说I0=1I_0=1

  • A=1A=1时,若I=0I=0AppDataAppData将从应用层发出;若I=1I=1,则AppDataAppData将由应用层接受。
  • A=0A=0时,则AppData:=L×[[0]]AppData:=L\times[[0]] (为L-byte操作),也就是说,此时protocol transcript包含了MACs的长度,但是没有相应的值,即所有的值都重置为了0。通过这种方式,当接收到不正确的MACs时,protocol会进行终止操作。

ii个block的输出,取决于操作op{ENC,MAC,PRF}op\in\{ENC,MAC,PRF\},输入有:前序的protocol transcript TrTr;当前block的input;前序block的application data。详细可表示为:
Outputi=InputiG(Tr,AdjDir(I0,operation),(AppData1...AppDatai1))Output_i=Input_i\oplus G(Tr, AdjDir(I_0,operation),(AppData_1||...||AppData_{i-1}))

其中GG为随机函数,ϵ\epsilon-indifferenctiable。
在这里插入图片描述

所有的STROBE协议,都必须以ADAD操作开始,且在ADAD操作中应有不同domain的分隔符。该分隔符需为通一资源标志符(Universal Resource Identifier, URI),以保证能唯一描述协议,防止各种跨协议攻击。

对于简单的协议,每个操作应在上下文中具有唯一的涵义,使得transcript可解析。对于复杂的协议,相同的操作可能有多重涵义,此时要想解析transcript,一种简单的方法时在transcript中做备注来区分。此时信息可以通过协议帧来传输,如TCP stream中的tag-length-value帧(tag表明message type)。在STROBE协议中,通过metadatametadata来区分,通过MM标签来标记,对操作无任何影响,仅仅用于hashed into the protocol transcript,这样的操作页可称为metaopmeta-op操作。
大多数协议,都是以明文格式来发送帧数据,这时会使用metaCLRmeta-CLR transaction(除了在transcript中具有MM标签外,与CLRCLR操作类似)。
若使用metaENCmeta-ENC操作,则相应的帧信息将被加密,这在图片隐写术和长度填充中有用。
在协议中若未传输足够的帧信息来保证完全可解析,可通过metaADmeta-AD操作来补充传送帧信息。

推荐的做法为:对于每个non-metadata操作,后面都紧跟一个metadata操作来做补充描述。
以OP来表示操作,info标签来描述协议中消息message的含义。则在Info标签中应包含消息的长度(除非在协议中为固定值或不可知)。同时以标签-操作符来描述帧信息及对应的操作符。(如meta-CLR,meta-AD,meta-CLR等)。

举例:ENC[app-ciphertext] (“hello”)可拆分为两个动作:
meta-CLR([[0x03,0x05,0x00]]); ENC(“hello”)

其中0x030x03标签代表app-ciphertext,[[0x05,0x00]]为length标签,代表的时5个bytes。

5. strobe的实例化

论文《The Strobe protocol framework》的附录B.1中指出,当采用keccak-f[1600]时,即b=1600b=1600,STROBE security为λ\lambda,有c=2λ,r+c=b,F=f[b]c=2\lambda,r+c=b,F=f[b],于是有r=bc=16002λr=b-c=1600-2\lambda

根据附录A.1可知,rr为sponge rate,cc为capacity。rr的取值范围为3r2563\leq r\leq256,为了减小功耗分析攻击,sponge rate会调整为r^=r/82=200λ/42,r/8=r^+2\hat{r}=r/8-2=200-\lambda/4-2, r/8=\hat{r}+2,对应的https://github.com/rozbb/strobe-rs中代码实现为:

		let rate = KECCAK_BLOCK_SIZE * 8 - (sec as usize) / 4 - 2; //KECCAK_BLOCK_SIZE =25, rate即为上文的$\hat{r}$
        assert!(rate >= 1);
        assert!(rate < 254);

rate即为上文的r^\hat{r}
初始化状态为:在这里插入图片描述
对应的代码实现为:

 		// Initialize state: st = F([0x01, R+2, 0x01, 0x00, 0x01, 0x60] + b"STROBEvX.Y.Z")
        let mut st_buf = [0u8; KECCAK_BLOCK_SIZE * 8];
        st_buf[0..6].copy_from_slice(&[0x01, (rate as u8) + 2, 0x01, 0x00, 0x01, 0x60]);
        st_buf[6..13].copy_from_slice(b"STROBEv");
        st_buf[13..18].copy_from_slice(STROBE_VERSION.as_bytes());
        //运行F函数,keccak-f[1600]
        let mut st = AlignedKeccakState(st_buf);
        keccakf_u8(&mut st);

        let mut strobe = Strobe {
            st: st,
            sec: sec,
            rate: rate,
            pos: 0,
            pos_begin: 0,
            is_receiver: None,
        };
 		// Mix the protocol into the state
        let _ = strobe.meta_ad(proto, false);
//对应地:
def_op_no_mut!(
        ad,
        meta_ad,
        OpFlags::A,
        "Mixes associated data into the internal state."
    );
// This defines an operation and meta-operation that does not mutate its input
macro_rules! def_op_no_mut {
    ($name:ident, $meta_name:ident, $flags:expr, $doc_str:expr) => (
        #[doc = $doc_str]
        pub fn $name(&mut self, data: &[u8], more: bool) {
            let flags = $flags;
            self.operate_no_mutate(flags, data, more);
        }

        #[doc = $doc_str]
        pub fn $meta_name(&mut self, data: &[u8], more: bool) {
            let flags = $flags | OpFlags::M;
            self.operate_no_mutate(flags, data, more);
        }
    )
}

	/// Performs the state transformation that corresponds to the given flags. If `more` is given,
    /// this will treat `data` as a continuation of the data given in the previous call to
    /// `operate`. This uses non-mutating variants of the specializations of the `duplex` function.
    pub(crate) fn operate_no_mutate(&mut self, flags: OpFlags, data: &[u8], more: bool) {
        assert!(!flags.contains(OpFlags::K), "Op flag K not implemented");

        if !more {
            self.begin_op(flags);
        }

        // There are no non-mutating variants of things with flags & (C | T | I) == C | T
        if flags.contains(OpFlags::C) && flags.contains(OpFlags::T) && !flags.contains(OpFlags::I) {
            panic!("operate_no_mutate called on something that requires mutation");
        } else if flags.contains(OpFlags::C) {
            // This is equivalent to a non-mutating form of the `duplex` operation in the Python
            // implementation, with `cbefore = True`
            self.overwrite(data);
        } else {
            // This is equivalent to the `duplex` operation in the Python implementation, with
            // `cbefore = cafter = False`
            self.absorb(data);
        };
    }

参考资料:
[1] https://strobe.sourceforge.io/
[2] https://github.com/rozbb/strobe-rs
[3] https://keccak.team/keccak.html
[4] 论文《The Strobe protocol framework
[5] strobe视频解说:https://www.youtube.com/watch?v=l7xV5z1eJLw
[6] https://www.cryptologie.net/article/408/noisestrobedisco/
[7] https://noisesocket.org/post/1/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!