【密码学】一文读懂MT19937

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
图片翻译,图片翻译 100张
简介: 瞄了一眼redis的源码,然后发现里面好玩的东西还挺多的,本文来聊一聊redis当中用到的一个随机数生成算法 mt19937,具体源码参见文末的参考资料,在这里就不贴到文本当中了。对于redis源码里面用的是mt19937-64本文先来看一下32位的版本,对于64位的版本,只不过状态当中元素用的是64位的元素,整个运算过程框架是类似的。「梅森旋转算法」(「Mersenne twister」)是一个伪随机数生成算法,由松本真和西村拓士在1997年提出来的,可以快速产生高质量的伪随机数,修正了古典随机数生成算法当中的很多缺陷。19937这个名字来源于周期长度为梅森素数 。

【密码学】一文读懂MT19937


]MO$QND[_P_8_@G]TCR8GZI.jpg

瞄了一眼redis的源码,然后发现里面好玩的东西还挺多的,本文来聊一聊redis当中用到的一个随机数生成算法 mt19937,具体源码参见文末的参考资料,在这里就不贴到文本当中了。对于redis源码里面用的是mt19937-64本文先来看一下32位的版本,对于64位的版本,只不过状态当中元素用的是64位的元素,整个运算过程框架是类似的。

「梅森旋转算法」「Mersenne twister」)是一个伪随机数生成算法,由松本真和西村拓士在1997年提出来的,可以快速产生高质量的伪随机数,修正了古典随机数生成算法当中的很多缺陷。19937这个名字来源于周期长度为梅森素数 。


生成器结构

OBAK1U[T7G]C@CA0)UAVAKD.pngMT19937生成器结构

如上图所示,mt19937的随机数生成器结构首先需要一个uint32的种子,然后生成一个具有624个uint32数组的状态数组。生成状态数组之后,进行一次旋转,最终可以输出624个随机的uint32。然后重复执行旋转操作,就可以得到一个周期为 的随机数生成器了。

对于mt19937整个计算过程来说,虽然比我之前提到过的线性同余法复杂不少,但是整个流程还是比较清晰的,对于里面的原理,我其实也了解的不是很多,因此在这里就不展开讲了,如果想了解原理的读者,可以参考文末的参考资料当中的论文进行学习,本文是指来聊一下这个东西具体是怎么计算的。到这里,这篇文章我就水完了,逃~~~


代码实现

老样子了,还是给出我写的两个语言的参考,注意本文讲的是32位的mt19937,再去看redis源码当中的实现的时候用的是mt19937-64。

Go

const (
  n = 624
  m = 397
)
type MT19937 struct {
  state []uint32
  index int
}
func New(seed uint32) *MT19937 {
  mt := &MT19937{
    state: make([]uint32, n),
    index: 0,
  }
  mt.state[0] = seed
  for i := uint32(1); i < n; i++ {
    mt.state[i] = 1812433253*(mt.state[i-1]^mt.state[i-1]>>30) + i
  }
  return mt
}
func (mt *MT19937) twist() {
  for i := uint32(0); i < n; i++ {
    y := (mt.state[i] & 0x80000000) + (mt.state[(i+1)%n] & 0x7fffffff)
    mt.state[i] = (y >> 1) ^ mt.state[(i+m)%n]
    if y%2 != 0 {
      mt.state[i] = mt.state[i] ^ 0x9908b0df
    }
  }
}
func (mt *MT19937) Uint32() uint32 {
  if mt.index == 0 {
    mt.twist()
  }
  y := mt.state[mt.index]
  y = y ^ y>>11
  y = y ^ y<<7&2636928640
  y = y ^ y<<15&4022730752
  y = y ^ y>>18
  mt.index = (mt.index + 1) % n
  return y
}

Rust

const N: usize = 624;
struct MT19937 {
    state: [u32; N],
    index: usize,
}
impl MT19937 {
    pub fn new(seed: u32) -> Self {
        let mut mt = MT19937 {
            state: [0; N],
            index: 0,
        };
        mt.state[0] = seed;
        for i in 1..N {
            mt.state[i] = 1812433253 * (mt.state[i - 1] ^ (mt.state[i - 1] >> 30)) + i as u32;
        }
        mt
    }
    fn twist(&mut self) {
        for i in 0..N {
            let x = (self.state[i] & 0x80000000) | (self.state[(i + 1) % N] & 0x7fffffff);
            let mut x_a = x >> 1;
            if x % 2 != 0 {
                x_a ^= 0x9908b0df;
            }
            self.state[i] = self.state[(i + 397) % N] ^ x_a;
        }
        self.index = 0;
    }
    fn rand(&mut self) -> u32 {
        if self.index >= N {
            self.twist();
        }
        let y = self.state[self.index];
        self.index += 1;
        y ^ y >> 11
    }
}


相关文章
|
存储 Rust 并行计算
【密码学】一文读懂XTS模式
这篇文章的灵感来源于我偶然翻到的一个某U盘有关磁盘加密的一个介绍(这一篇不是广告蛤), 然后发现这个模式我之前还真没遇到过,因此呢,就学习了一下,就出来了这一篇文章。
4920 0
【密码学】一文读懂XTS模式
|
Rust 算法 Go
【密码学】一文读懂FNV Hash
FNV哈希全名为Fowler-Noll-Vo算法,是以三位发明人Glenn Fowler,Landon Curt Noll,Phong Vo的名字来命名的,最早在1991年提出。它可以快速hash大量的数据并保持较小的冲突概率,适合hash一些相近的字符串比如IP地址、URL、文件名等等。目前FNV算法有三个版本,分别是: FNV-0(已废弃)、FNV-1以及FNV-1a。这三个算法的结构非常相似,因此呢,在这里就一块说了。
2649 0
【密码学】一文读懂FNV Hash
|
Rust 算法 Go
【密码学】一文读懂MurMurHash3
本文应该是MurMurHash算法介绍的最后一篇,来一起看一下最新的MurMurHash算法的具体过程,对于最新的算法来说,整个流程和之前的其实也比较相似,这里从维基百科当中找到了伪代码,也就不贴出来Google官方给出的推荐代码了,先来看一下维基百科给出的伪代码,这里只有32位的伪代码。
2058 0
【密码学】一文读懂MurMurHash3
|
Rust 算法 安全
【密码学】一文读懂MurMurHash2
上次我们聊过了一代的MurMurHash算法,是的,我又来水文章了,今天呢,接着来聊一下二代的MurMurHash算法,二代算法的整体结构实际上和一代算法差不太多,只是对于每一轮数据的处理过程当中的运算有一些差异,算法的来源依然是来自于Google官网给提供的源码,对着源码看的结构,对于这个算法呢,有两个版本,一个是32位的,一个是64位的,对于32位的算法和64位的算法,区别在于两个初始的魔数不同,整体运算过程还是十分相似的。
2132 0
【密码学】一文读懂MurMurHash2
|
Web App开发 Rust 算法
【密码学】一文读懂ChaCha20
好久没写新的加密算法的原理了, 这次所选取的加密算法结构比较简单, 一起来看一下吧。
7372 0
【密码学】一文读懂ChaCha20
|
算法 数据安全/隐私保护
【密码学】一文读懂Whirlpool
首先呢,祝大家今晚节日快乐,Whirlpool是由Vincent Rijmen(高级加密标准的联合创始人)和Paulo S.L.M.Barreto设计的,后者于2000年首次提出了它。
1077 0
【密码学】一文读懂Whirlpool
|
Rust 算法 网络安全
【密码学】一文读懂CMAC
介于上一篇文章比较水,然后这个和上一篇也比较相似,CMAC是为了解决DAA当中安全性不足的问题而出现的,这个算法一共有三个密钥,K, K1, K2, 其中K1和K2可以由K导出,接下来就来一起看一下CMAC的具体过程吧,这一篇文章其实也不长。
3582 0
【密码学】一文读懂CMAC
|
算法 安全 Go
【密码学】一文读懂HKDF
我这又来水一篇文章,来聊一下HKDF(基于HMAC的密钥导出函数)。密钥派生函数是密钥管理的组成部分,他的目标是通过一些初始的数据派生出来密码学安全的随机密钥。
3040 1
【密码学】一文读懂HKDF
|
Rust 算法 数据安全/隐私保护
【密码学】一文读懂SM3
SM3是中华人民共和国政府采用的一种密码散列函数标准,前身为SCH4杂凑算法,由国家密码管理局于2010年12月17日发布,相关标准为&quot;GM/T 0004-2012 《SM3密码杂凑算法》&quot;。
3204 0
【密码学】一文读懂SM3
|
算法 数据安全/隐私保护
【密码学】一文读懂SHA-1
SHA-1(Secure Hash Algorithm 1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦资料处理标准(FIPS)。SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值通常的呈现形式为40个十六进制数。
1177 1
【密码学】一文读懂SHA-1