forked from Trisia/randomness
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdetect.go
125 lines (118 loc) · 2.77 KB
/
detect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package detect
import (
"errors"
"fmt"
"github.com/Trisia/randomness"
"io"
"math"
)
// FactoryDetect 出厂检测,15种检测,每组 10^6比特,分50组
// source: 随机源
func FactoryDetect(source io.Reader) (bool, error) {
s := 50
t := Threshold(s)
buf := make([]byte, 1000_000/8)
counters := make([]int, 15)
for i := 0; i < s; i++ {
_, err := source.Read(buf)
if err != nil {
return false, err
}
resArr := Round15(buf)
for idx, result := range resArr {
if result.Pass {
counters[idx]++
}
}
}
for i, n := range counters {
if n < t {
return false, fmt.Errorf("%s %d/%d", randomness.TestMethodArr[i].Name, n, s)
}
}
return true, nil
}
// PowerOnDetect 上电自检,15种检测,每组 10^6比特,分20组
// source: 随机源
func PowerOnDetect(source io.Reader) (bool, error) {
s := 20
t := Threshold(s)
buf := make([]byte, 1000_000/8)
counters := make([]int, 15)
for i := 0; i < s; i++ {
_, err := source.Read(buf)
if err != nil {
return false, err
}
resArr := Round15(buf)
for idx, result := range resArr {
if result.Pass {
counters[idx]++
}
}
}
for i, n := range counters {
if n < t {
return false, fmt.Errorf("%s %d/%d", randomness.TestMethodArr[i].Name, n, s)
}
}
return true, nil
}
// PeriodDetect 周期性检测,除去离散傅里叶检测、线型复杂度检测、通用统计的12种检测
// 检测 20组,每组 20000比特
// source: 随机源
func PeriodDetect(source io.Reader) (bool, error) {
s := 20
t := Threshold(s)
buf := make([]byte, 20000/8)
counters := make([]int, 12)
for i := 0; i < s; i++ {
_, err := source.Read(buf)
if err != nil {
return false, err
}
resArr := Round12(buf)
for idx, result := range resArr {
if result.Pass {
counters[idx]++
}
}
}
for i, n := range counters {
if n < t {
return false, fmt.Errorf("%s %d/%d", randomness.TestMethodArr[i].Name, n, s)
}
}
return true, nil
}
// SingleDetect 单次检测,单根据实际应用时每次才随机数的大小确定,检测采用扑克检测
// source: 随机源
// numByte: 采集字节数,不能小于16
func SingleDetect(source io.Reader, numByte int) (bool, error) {
data := make([]byte, numByte)
_, err := source.Read(data)
if err != nil {
return false, err
}
n := len(data) * 8
if n < 128 {
return false, errors.New("长度不能低于128比特(16 byte)")
}
m := 4
if n < 320 {
m = 2
} else if n/8 >= 1280 { // n/m >= 5 * 2^m
m = 8
}
p := randomness.PokerTestBytes(data, m)
return p >= randomness.Alpha, nil
}
// Threshold 样本通过检测判定数量
// s: 检测样本数
// return 通过检测需要的样本数量
func Threshold(s int) int {
a := randomness.Alpha
_s := float64(s)
r := _s * (1 - a - 3*math.Sqrt((a*(1-a))/_s))
return int(math.Ceil(r))
}