-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
148 lines (126 loc) · 4.78 KB
/
main.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
import (
"fmt"
"math/rand"
"strconv"
)
// randomGen2 - функція що генерує випадкову послідовність 20000 біт
// на основі функції rand.Uint32, яка генерує 32 бітні випадкові значення;
// повертає масив uint32
func randomGen2() []uint32 {
var bitArray []uint32
for i := 0; i < 625; i++ {
bitArray = append(bitArray, rand.Uint32())
}
return bitArray
}
// getHex виводить послідовність біт у 16-річному форматі
func getHex(bitArray []uint32) string {
var hexString string
for i := 0; i < len(bitArray); i++ {
hexString += strconv.FormatUint(uint64(bitArray[i]), 16)
}
return hexString
}
// Тест на відповідність кількості 0/1 стандарту FIPS-140
func monobit(bitArray []uint32) bool {
var onesCount uint32
for i := 0; i < len(bitArray); i++ {
for j := 31; j >= 0; j-- {
onesCount += (bitArray[i] >> j) & 1
}
}
if onesCount < 9654 || onesCount > 10346 {
return false
}
return true
}
// Тест Покера
func pokerTest(bitArray []uint32) bool {
// entryFrequency - масив який зберігає кількість входжень кожного з блоків; блоки розміром 4, тому можливих різних блоків - 16
var entryFrequency [16]float32
// blockCount - кількість блоків розміром 4
blockCount := float64(len(bitArray) * 8)
// quadsSum - сума квадратів кількості входження кожного з блоків
var quadsSum float64
for i := 0; i < len(bitArray); i++ {
for j := 0; j < 32; j += 4 {
entryFrequency[(bitArray[i]>>j)&0b1111] += 1
}
}
for i := 0; i < 16; i++ {
quadsSum += float64(entryFrequency[i] * entryFrequency[i])
}
X := (16/blockCount)*quadsSum - blockCount
if X < 1.03 || X > 57.4 {
return false
}
return true
}
// seriesCheck2 приймає на вхід послідовність 20000 біт(big endian);
// true якщо максимальна серія та кількість входжень серій відповідають стандарту FIPS-140
func seriesCheck2(bitArray []uint32) bool {
// series масив який зберігає серії різної довжини 0 і 1 відповідно
var series [2][6]int
// maxSeria - найбільша серія 1 або 0
maxSeria := 0
// seria - поточна серія 1 або 0
seria := 0
// digit - вказує на серію одиниць(=1) чи нулів(=0)
digit := (bitArray[0] >> 31) & 1
// Проходимось в циклі по всім бітам
for i := 0; i < len(bitArray); i++ {
for j := 31; j >= 0; j-- {
// Визначаємо поточний біт
bit := (bitArray[i] >> j) & 1
// Якщо поточний біт = поточній серії -> seria += 1
if bit == digit {
seria += 1
} else { // В іншому випадку перевіряємо чи є поточна серія максимальною, якщо так - то замінюємо максимальну на поточну
if seria > maxSeria {
maxSeria = seria
}
// Якщо серія більша за 6 - прирівнюємо серію до 6 (в таблиці останнє значення 6+)
if seria > 6 {
seria = 6
}
// Додаємо 1 до комірки що зберігає кількістьвходжень поточної серії, змінюємо поточну серію на протилежну, поточна серія = 1
series[digit][seria-1] += 1
digit = bit
seria = 1
}
}
}
// Для врахування останньої серії
if seria > maxSeria {
maxSeria = seria
}
if seria > 6 {
seria = 6
}
series[digit][seria-1] += 1
// Перевірка чи відповідає стандарту максимальна довжина серії
if maxSeria > 36 {
return false
}
// Діапазон значень входжень кожної з серій відповідно до стандарту
compareTable := [6][2]int{{2267, 2733}, {1079, 1421}, {502, 748}, {223, 402}, {90, 223}, {90, 223}}
// Перевірка належності кількості входжень проміжку зазначеному в стандарті
for i := 0; i < 6; i++ {
for j := 0; j < 2; j++ {
if series[j][i] < compareTable[i][0] || series[j][i] > compareTable[i][1] {
return false
}
}
}
return true
}
func main() {
var randomNumber []uint32
for {
randomNumber = randomGen2()
if monobit(randomNumber) && seriesCheck2(randomNumber) && pokerTest(randomNumber) {break}
}
fmt.Println(getHex(randomNumber))
fmt.Println("The sequence is quite random")
}