杂谈-字节数组和int之间的转换
本文还是来随便聊一聊,我们在去看一些密码学算法的结构的过程当中,我们经常的会发现,这些结构内部的数据的处理方式并不都是根据字节来处理的,有可能他们对于数据的处理用的u32或者说是u64,之前我们说了,在计算机的内部,最小的单位是字节,那么我们怎么将这个字节处理成为结构当中需要的u32或者u64呢?本文接下来就来聊一下他们之间的转换过程(还是老样子,只考虑无符号数)
字节数组和int之间的转换
一个前置的知识,一个int所占用的大小为32bit, 一个字节所占用的大小为8bit,因此呢,通过这个大小我们可以发现,一个int应该是可以用4个字节来表示的,同样的一个int也可以转换成为4个字节。
从上图可以看出,我们怎么去放,实际上是有两种方法的,第一种就是直观的放置方法,也就是直接放下去,还有第二种方法,就是倒过来去放,这两种其实是都存在的,就好比md5 就采取的第一种方案,而sha系列的算法都采用的第二种的方案。如果有忘记了这两种算法的读者可以去看一下我之前写过的相关的文章哈。
那么我们如何用编程语言来实现这个过程呢,这里用c的代码写了,对于某一些语言是带有转换之类的函数的,比如Python的pack
和unpack
,rust的to_le_bytes()
等等。
- u8 转 u32
这个转换过程比较简单,通过我们之前讲到过的移位运算以及或运算就可以了,直接上代码
uint32_t u8to32(const uint8_t *p) { return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; }
这个采用的从前往后的写法,如果需要第二种,序号反过来写就可以了。
- u32 转 u8
unsigned char bytes[4]; unsigned long n = 123; bytes[0] = (n >> 24) & 0xFF; bytes[1] = (n >> 16) & 0xFF; bytes[2] = (n >> 8) & 0xFF; bytes[3] = n & 0xFF;
这里同样的采用的是从前往后的写法,第二种序号反过来就可以了。
简单的解释一下,我们为什么可以通过移位的运算来实现这种效果,因为我们知道,位运算实际上是bit的移位运算,因此呢,我们要是右移8bit的话,那么是不是我们就移除掉了一个字节,然后 & 0xFF
之后,是不是就得到了最后的一个字节,不断这么去重复去做,就拿到了每一个字节了。
小结
本篇文章只讲了32位的整数和bytes之间的转换,在密码学当中,实际上也有用64位整数的,读者可以自行思考一下,对于64位应该怎么处理。