Skip to content

Commit

Permalink
move certification process to tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Aizen committed Oct 5, 2024
1 parent 0409c62 commit f7e2e35
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 51 deletions.
51 changes: 0 additions & 51 deletions cmd/genpw/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ type Passphrase struct {

func main() {
g := cp.NewInstance()
cert := flag.Bool("c", false, "run entropy certification algorithm\nusers not necessarily need to concern with this detail.")
depth := flag.Uint64("cd", 1, "certification effort.\nA larger number leads to more accurate results\nat the expense of exponentially longer completion times.")
f_pattern := flag.String("p", "W.w.w",
`pattern used to generate passphrase e.g. try:
-p WWW20dd
Expand All @@ -33,9 +31,6 @@ func main() {
passwords := flag.Uint64("n", 6, "number of passwords to generate")
flag.Parse()
pattern := *f_pattern
if *cert {
certify(pattern, *depth)
}

pws := []Passphrase{}
for range *passwords {
Expand Down Expand Up @@ -65,49 +60,3 @@ func main() {
fmt.Printf("%s%s%.2f %.2f\n", p.F, padding, (p.H-1)/math.Log2(10), p.H)
}
}

func certify(pattern string, udepth uint64) {
g := cp.NewInstance()
cnt := make(map[string]int)
iN := 0
Q := 128
nominal_H := 0.0
nominal_H2 := 0.0
cnt_nom_H := 0.0
for {
Q += Q / 14
for range Q {
w, nh := g.GenFromPattern(pattern)
nominal_H += nh
nominal_H2 += nh * nh
cnt_nom_H++
cnt[w]++
iN++
}

n := float64(iN)
m := float64(len(cnt))
H := 0.0
for _, iC := range cnt {
c := float64(iC)
p := (c / n)
H -= p * math.Log2(p)
}
H += (m - 1) / (2 * n)
fmt.Print("\r")
CH := int(2 * H)
for i := 0; i <= CH; i++ {
fmt.Print("|")
}
nomH := nominal_H / cnt_nom_H
nomH2 := nominal_H2 / cnt_nom_H
stddev := math.Sqrt(max(nomH2-nomH*nomH, 0.0001))
gap := nomH - H
fmt.Printf("%v | E[H]-E=%.2f E[H] = %.2f ∂E[H] = %.2f ", strings.Repeat(" ", 60-CH), gap, nomH, stddev)
if gap < stddev/(1+float64(udepth)) {
fmt.Print("\n")
fmt.Println(H)
break
}
}
}
51 changes: 51 additions & 0 deletions cryptipass.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,54 @@ func (g *Generator) GenWord(c rune) (string, float64) {
h_head += h_leng
return head, h_head
}

type CertifyResult struct {
NominalH float64
Gap float64
StdDev float64
}

func Certify(Gen func() (string, float64)) CertifyResult {
nominal_H := 0.0
nominal_H2 := 0.0
cnt_nom_H := 0.0
for range 1000 {
//pilot run to estimate budjet
_, nh := Gen()
nominal_H += nh
nominal_H2 += nh * nh
cnt_nom_H++
}
nomH := nominal_H / cnt_nom_H
nomH2 := nominal_H2 / cnt_nom_H
stddev := math.Sqrt(max(nomH2-nomH*nomH, 0.0001))
target := nominal_H/cnt_nom_H + 3 + stddev
cnt := make(map[string]int)
n := float64(0)

for {
w, nh := Gen()
nominal_H += nh
nominal_H2 += nh * nh
cnt_nom_H++
cnt[w]++
n++
if math.Log2(n) >= target {
break
}
}

m := float64(len(cnt))
H := 0.0
for _, iC := range cnt {
c := float64(iC)
p := (c / n)
H -= p * math.Log2(p)
}
H += (m - 1) / (2 * n)
nomH = nominal_H / cnt_nom_H
nomH2 = nominal_H2 / cnt_nom_H
stddev = math.Sqrt(max(nomH2-nomH*nomH, 0.0001))
gap := nomH - H
return CertifyResult{NominalH: nomH, Gap: gap, StdDev: stddev}
}
43 changes: 43 additions & 0 deletions cryptipass_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package cryptipass_test

import (
"fmt"
"math"
"math/rand/v2"
"strings"
"testing"

Expand All @@ -10,6 +13,7 @@ import (
func TestBasic(t *testing.T) {
g := cryptipass.NewInstance()
pw, H := g.GenPassphrase(4)

if len(pw) < 15 {
t.Fatalf(`Wrong length "%s"`, pw)
}
Expand All @@ -19,6 +23,45 @@ func TestBasic(t *testing.T) {
}
}

func TestCert(t *testing.T) {
g := cryptipass.Generator{}
g.Rng = rand.New(rand.NewPCG(37512033, 27996124))

type FN func() (string, float64)
funcs := []FN{
func() (string, float64) {
return g.GenFromPattern("Cccs")
},
func() (string, float64) {
return g.GenFromPattern("ddss")
},
func() (string, float64) {
return g.GenFromPattern("Cdd")
},
func() (string, float64) {
r := g.Rng.IntN(2)
s, h := g.GenFromPattern(strings.Repeat("cs", 1+r))
h += 1
return s, h
},
func() (string, float64) {
r, h := g.PickLength()
r2, h2 := g.PickLength()
return fmt.Sprint(r, r2), h + h2
},
}

for i, x := range funcs {
X := cryptipass.Certify(x)
if math.Abs(X.Gap) >= 0.5 {
t.Fatal("failed certification of function", i, X)
} else {
t.Log("passed certification of function", i, X, ", OK!")
}
}

}

// TestGenPassphrase tests the GenPassphrase function for generating a passphrase and validating its length.
func TestGenPassphrase(t *testing.T) {
g := cryptipass.NewInstance()
Expand Down

0 comments on commit f7e2e35

Please sign in to comment.