220 lines
4.3 KiB
Go
220 lines
4.3 KiB
Go
//go:build ignore
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math"
|
|
"os"
|
|
"path"
|
|
"runtime"
|
|
"sync"
|
|
|
|
"xdx.jelly/xgcl/grand/statistics"
|
|
)
|
|
|
|
var suit = []struct {
|
|
name string
|
|
fn func([]byte) bool
|
|
}{
|
|
{
|
|
name: "单比特频数检测 ",
|
|
fn: statistics.Frequency,
|
|
},
|
|
|
|
{
|
|
name: "块内频数检测 ",
|
|
fn: statistics.BlockFrequency,
|
|
},
|
|
{
|
|
name: "扑克检测, m=4 ",
|
|
fn: statistics.Poker4,
|
|
},
|
|
{
|
|
name: "扑克检测, m=8 ",
|
|
fn: statistics.Poker8,
|
|
},
|
|
{
|
|
name: "重叠子序列检测, m=2",
|
|
fn: statistics.Serial2,
|
|
},
|
|
{
|
|
name: "重叠子序列检测, m=5",
|
|
fn: statistics.Serial5,
|
|
},
|
|
{
|
|
name: "游程总数检测 ",
|
|
fn: statistics.Runs,
|
|
},
|
|
{
|
|
name: "游程分布检测 ",
|
|
fn: statistics.RunsDistribution,
|
|
},
|
|
{
|
|
name: "二元推导检测, k=3 ",
|
|
fn: statistics.BinaryDerivative3,
|
|
},
|
|
{
|
|
name: "二元推导检测, k=7 ",
|
|
fn: statistics.BinaryDerivative7,
|
|
},
|
|
{
|
|
name: "自相关检测, d=1 ",
|
|
fn: statistics.Autocorrelation1,
|
|
},
|
|
{
|
|
name: "自相关检测, d=2 ",
|
|
fn: statistics.Autocorrelation2,
|
|
},
|
|
{
|
|
name: "自相关检测, d=8 ",
|
|
fn: statistics.Autocorrelation8,
|
|
},
|
|
{
|
|
name: "自相关检测, d=16 ",
|
|
fn: statistics.Autocorrelation16,
|
|
},
|
|
{
|
|
name: "矩阵秩检测 ",
|
|
fn: statistics.Rank,
|
|
},
|
|
{
|
|
name: "累加和检测 ",
|
|
fn: statistics.CumulativeSums,
|
|
},
|
|
{
|
|
name: "近似熵检测 ",
|
|
fn: statistics.ApproximateEntropy,
|
|
},
|
|
{
|
|
name: "线性复杂度检测 ",
|
|
fn: statistics.LinearComplexity,
|
|
},
|
|
{
|
|
name: "Maurer通用统计检测 ",
|
|
fn: statistics.Universal,
|
|
},
|
|
{
|
|
name: "离散傅立叶检测 ",
|
|
fn: statistics.DiscreteFourierTransform,
|
|
},
|
|
}
|
|
|
|
type payload struct {
|
|
e []byte
|
|
fn func([]byte) bool
|
|
}
|
|
|
|
func worker(in chan *payload, out chan bool, done chan struct{}) {
|
|
for {
|
|
select {
|
|
case p := <-in:
|
|
out <- p.fn(p.e) // fn may panic
|
|
case <-done:
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
dataDir := flag.String("d", "./data", "The directory of random data, default is \"./data\"")
|
|
flag.Parse()
|
|
fmt.Println("=======================================================")
|
|
fmt.Println(" 测试文件夹:", *dataDir)
|
|
epsilons := make([][]byte, 0)
|
|
|
|
fs, err := ioutil.ReadDir(*dataDir)
|
|
if err != nil {
|
|
fmt.Println("文件夹读取错误: ", err)
|
|
return
|
|
}
|
|
|
|
for _, file := range fs {
|
|
if !file.IsDir() {
|
|
epsilon, err := readFile(path.Join(*dataDir, file.Name()))
|
|
if err != nil {
|
|
fmt.Println("文件读取错误: ", err)
|
|
return
|
|
}
|
|
epsilons = append(epsilons, epsilon)
|
|
}
|
|
}
|
|
fmt.Printf(" 共有随机数文件%d个,每个文件%d比特\n", len(epsilons), len(epsilons[0]))
|
|
bound := lowerBound(len(epsilons))
|
|
fmt.Printf(" 每组检测通过的样本数必须不小于: %d\n", bound)
|
|
fmt.Println("=======================================================")
|
|
|
|
threads := runtime.NumCPU()
|
|
in := make(chan *payload, threads)
|
|
out := make(chan bool, threads)
|
|
done := make(chan struct{})
|
|
|
|
for i := 0; i < threads; i++ {
|
|
go worker(in, out, done)
|
|
}
|
|
|
|
// for {
|
|
for _, t := range suit {
|
|
// for _, t := range suit[len(suit)-1:] {
|
|
sum := 0
|
|
var wg sync.WaitGroup
|
|
wg.Add(len(epsilons))
|
|
go func() {
|
|
for _, e := range epsilons {
|
|
in <- &payload{
|
|
e: e,
|
|
fn: t.fn,
|
|
}
|
|
}
|
|
}()
|
|
|
|
go func() {
|
|
for i := 0; i < len(epsilons); i++ {
|
|
b := <-out
|
|
if b {
|
|
sum += 1
|
|
}
|
|
wg.Done()
|
|
}
|
|
}()
|
|
|
|
wg.Wait()
|
|
|
|
if sum < bound {
|
|
fmt.Printf("[x] %s 【失败】: %d / %d\n", t.name, sum, len(epsilons))
|
|
} else {
|
|
fmt.Printf("[o] %s 【通过】: %d / %d\n", t.name, sum, len(epsilons))
|
|
}
|
|
}
|
|
// }
|
|
}
|
|
|
|
// readFile read from fileName and convert each bit to byte
|
|
func readFile(fileName string) ([]byte, error) {
|
|
content, err := os.ReadFile(fileName)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
bits := make([]byte, 0, len(content)*8)
|
|
for _, c := range content {
|
|
bits = append(bits, (c>>7)&1)
|
|
bits = append(bits, (c>>6)&1)
|
|
bits = append(bits, (c>>5)&1)
|
|
bits = append(bits, (c>>4)&1)
|
|
bits = append(bits, (c>>3)&1)
|
|
bits = append(bits, (c>>2)&1)
|
|
bits = append(bits, (c>>1)&1)
|
|
bits = append(bits, (c>>0)&1)
|
|
}
|
|
return bits, nil
|
|
}
|
|
|
|
const alpha float64 = 0.01
|
|
|
|
func lowerBound(samples int) int {
|
|
return int(math.Ceil((1 - alpha - 3*math.Sqrt((alpha*(1-alpha))/float64(samples))) * float64(samples)))
|
|
}
|