-
Notifications
You must be signed in to change notification settings - Fork 0
/
dual_ec_drbg.go
119 lines (95 loc) · 2.28 KB
/
dual_ec_drbg.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
package pnc
import (
"errors"
"math/big"
"github.com/46bit/pnc/ec"
)
type DualECDRBG struct {
C *ec.PrimeCurve
Q *ec.Point
S *big.Int
Sp *ec.Point
Z *big.Int
Zp *ec.Point
ZBytes []byte
StateIndex uint64
StateBit uint32
}
func NewDualECDRBG(c *ec.PrimeCurve, qx, qy, seed *big.Int) *DualECDRBG {
g := DualECDRBG{c, &ec.Point{qx, qy, true}, big.NewInt(0), nil, big.NewInt(0), nil, nil, 0, 0}
g.seed(seed)
return &g
}
// Seed is twice security_strength bits long (at least 256)
func (g *DualECDRBG) seed(seed *big.Int) {
g.S = seed
// To match OpenSSL, we perform two rounds before giving any output.
g.generate_number()
g.generate_number()
}
func (g *DualECDRBG) generate_number() {
g.StateIndex++
g.Sp = g.C.ScalarMultiply(g.S, g.C.G)
g.S = g.Sp.X
g.Zp = g.C.ScalarMultiply(g.S, g.Q)
g.Z = g.Zp.X
// We use .Bytes() so as to extract Z in big-endian format. This matches
// OpenSSL behaviour. We drop the first 16 bits by initialising g.StateBit
// as 16.
g.ZBytes = g.Z.Bytes()
g.StateBit = 16
}
func (g *DualECDRBG) Selfcheck() error {
if !g.C.Satisfied(g.Sp) {
return errors.New("S is not on curve.")
}
if !g.C.Satisfied(g.Zp) {
return errors.New("Z is not on curve.")
}
if !g.Sp.Finite {
return errors.New("S is infinite.")
}
if !g.Zp.Finite {
return errors.New("Z is infinite.")
}
return nil
}
func (g *DualECDRBG) Bit() uint32 {
if int(g.StateBit) >= len(g.ZBytes) * 8 {
g.generate_number()
}
z_byte := g.ZBytes[g.StateBit / 8]
z_bit_shift := 7 - (g.StateBit % 8)
z_bit := 1 & (z_byte >> z_bit_shift)
g.StateBit++
return uint32(z_bit)
}
func (g *DualECDRBG) Urand32() uint32 {
v := uint32(0)
for i := 0; i < 32; i++ {
v = (v<<1) + g.Bit()
}
return v
}
func (g *DualECDRBG) Byte() byte {
if g.StateBit % 8 != 0 {
g.StateBit = ((g.StateBit + 8) >> 3) << 3
}
if int(g.StateBit) >= len(g.ZBytes) * 8 {
g.generate_number()
}
z_byte := g.ZBytes[g.StateBit / 8]
g.StateBit += 8
return z_byte
}
func (g *DualECDRBG) Bytes(length uint32) []byte {
bs := make([]byte, length)
for i := uint32(0); i < length; i++ {
bs[i] = g.ZBytes[g.StateBit / 8]
g.StateBit += 8
if int(g.StateBit / 8) >= len(g.ZBytes) {
g.generate_number()
}
}
return bs
}