Untempering reverses the bitwise transformation applied by MT19937 to each internal state word before output. Given tempered output y4, it reconstructs the earlier values y3, y2, y1, and finally the original y. section 3.1.2
The reversal proceeds through the same XOR-shift-and stages in reverse order:
- Recover y3 from y4 with y3 = y4 ^ (y4 >> L). section 3.1.2
- Recover y2 from y3 with the masked left-shift XOR using T and C. section 3.1.2
- Recover y1 from y2 by repeating the masked left-shift reconstruction through progressively shifted intermediates. section 3.1.2
- Recover the original y from y1 by applying repeated right shifts and XOR operations. section 3.1.2
Listing 3.11 exploit_mt19937.go
func untemper(y4 uint32) uint32 {
// recover y3 from y4
y3 := y4 ^ (y4 >> impl_mt19937.L)
// recover y2 from y3
y2 := y3 ^ (y3<<impl_mt19937.T)&impl_mt19937.C
// recover y1 from y2
y2_0 := y2 << impl_mt19937.S
y2_1 := y2 ^ (y2_0 & impl_mt19937.B)
y2_2 := y2_1 << impl_mt19937.S
y2_3 := y2 ^ (y2_2 & impl_mt19937.B)
y2_4 := y2_3 << impl_mt19937.S
y2_5 := y2 ^ (y2_4 & impl_mt19937.B)
y2_6 := y2_5 << impl_mt19937.S
y2_7 := y2 ^ (y2_6 & impl_mt19937.B)
y2_8 := y2_7 << impl_mt19937.S
y1 := y2 ^ (y2_8 & impl_mt19937.B)
// recover y from y1
y1_0 := y1 >> impl_mt19937.U
y1_1 := y1 ^ y1_0
y1_2 := y1_1 >> impl_mt19937.U
y := y1 ^ y1_2
return y
}
The Go implementation makes each reversal stage explicit and can be used to trace how a tempered output becomes an internal state word. section 3.1.2
Recovering an MT19937 state
A cloning attack applies untemper to N observed outputs, stores the recovered words, and initializes a new MT19937 with that state. Subsequent cloned and original outputs match in the test. section 3.1.2
