/
util.go
92 lines (80 loc) · 2.47 KB
/
util.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
package spg
import (
rand "crypto/rand"
"encoding/binary"
"fmt"
"math"
"strings"
)
// subtractString returns a copy of source with any characters that appear in remove removed.
// It does not presever order.
func subtractString(source, remove string) string {
src := setFromString(source)
rm := setFromString(remove)
diff := src.Difference(rm)
out := stringFromSet(diff)
return out
}
// nFromString picks characters from a sting. This is for internal use only. It does not check for duplicates in the string
func nFromString(ab string, n int) (string, float64) {
if len(ab) == 0 {
return "", 0.0
}
if n < 1 {
return "", 0.0
}
ent := float64(n) * math.Log2(float64(len(ab)))
sep := ""
rAB := strings.Split(ab, "") // an AlphaBet of runes
for i := 1; i <= n; i++ {
sep += string(rAB[randomUint32n(uint32(len(rAB)))])
}
return sep, ent
}
// randomUint32 creates a random 32 bit unsigned integer
func randomUint32() uint32 {
b := make([]byte, 4)
_, err := rand.Read(b)
if err != nil {
panic("PRNG gen error:" + err.Error())
}
return binary.BigEndian.Uint32(b)
}
// entropySimple takes the password length and the number of elements in the alphabet
// (nelem would be number of words in a wordlist or number of characters in the alphabet
// from which the password is generated).
// It returns a float64
func entropySimple(length int, nelem int) FloatE {
// The entropy of, say, a length character password
// with characters drawn for letters and digits (so nelem is 62) would be
// length * log2(62).
if nelem < 1 {
// We will end up returning NaN or -Inf, so we are only logging here
fmt.Printf("entropySimple: There must be a positive number of elements. Not %d\n", nelem)
}
entPerUnit := math.Log2(float64(nelem))
return FloatE(float64(length) * entPerUnit)
}
// randomUint32n returns, as a uint32, a non-negative random number in [0,n) from a cryptographic appropriate source.
// It panics if a security-sensitive random number cannot be created or if n == 0.
// Care is taken to avoid modulo bias.
//
// Based on Int31n from the math/rand package..
func randomUint32n(n uint32) uint32 {
if n < 1 {
panic("randomUint32n called with 0")
}
if n&(n-1) == 0 { // n is power of two, can mask
return randomUint32() & (n - 1)
}
discard := uint32(math.MaxUint32 - math.MaxUint32%n)
v := randomUint32()
for v >= discard {
v = randomUint32()
}
return v % n
}
/**
** Copyright 2018 AgileBits, Inc.
** Licensed under the Apache License, Version 2.0 (the "License").
**/