func getServerSession(user string, password string, salt []byte, keyA *big.Int, keyB *big.Int, keyb *big.Int) []byte { prime, _, _ := getPrime() u := getScramble(keyA, keyB) v := getVerifier(user, password, salt) vu := mathutil.ModPowBigInt(v, u, prime) avu := new(big.Int).Mod(new(big.Int).Mul(keyA, vu), prime) sessionSecret := mathutil.ModPowBigInt(avu, keyb, prime) return bigToSha1(sessionSecret) }
func getClientSession(user string, password string, salt []byte, keyA *big.Int, keyB *big.Int, keya *big.Int) []byte { prime, g, k := getPrime() u := getScramble(keyA, keyB) x := getUserHash(salt, user, password) gx := mathutil.ModPowBigInt(g, x, prime) // gx = pow(g, x, N) kgx := new(big.Int).Mod(new(big.Int).Mul(k, gx), prime) // kgx = (k * gx) % N diff := new(big.Int).Mod(new(big.Int).Sub(keyB, kgx), prime) // diff = (B - kgx) % N ux := new(big.Int).Mod(new(big.Int).Mul(u, x), prime) // ux = (u * x) % N aux := new(big.Int).Mod(new(big.Int).Add(keya, ux), prime) // aux = (a + ux) % N sessionSecret := mathutil.ModPowBigInt(diff, aux, prime) // (B - kg^x) ^ (a + ux) return bigToSha1(sessionSecret) }
func getClientSeed() (keyA *big.Int, keya *big.Int) { prime, g, _ := getPrime() keya = new(big.Int).Rand(rand.New(rand.NewSource(time.Now().UnixNano())), bigFromString("340282366920938463463374607431768211456")) // 1 << 128 keyA = mathutil.ModPowBigInt(g, keya, prime) return }
func getServerSeed(v *big.Int) (keyB *big.Int, keyb *big.Int) { prime, g, k := getPrime() keyb = new(big.Int).Rand(rand.New(rand.NewSource(time.Now().UnixNano())), bigFromString("340282366920938463463374607431768211456")) // 1 << 128 gb := mathutil.ModPowBigInt(g, keyb, prime) // gb = pow(g, b, N) kv := new(big.Int).Mod(new(big.Int).Mul(k, v), prime) // kv = (k * v) % N keyB = new(big.Int).Mod(new(big.Int).Add(kv, gb), prime) // B = (kv + gb) % N return }
func benchmarkModPowBig(b *testing.B, base, e, m uint32) { b.StopTimer() bb := big.NewInt(int64(base)) ee := New(e) mm := New(m) runtime.GC() b.StartTimer() for i := 0; i < b.N; i++ { mathutil.ModPowBigInt(bb, ee, mm) } }
func main() { runtime.GOMAXPROCS(2) oClass := flag.Uint64("c", 2, `factor "class" number`) oDuration := flag.Duration("d", time.Second, "duration to spend on one class") flag.Parse() class := *oClass for class&1 != 0 { class >>= 1 } class = mathutil.MaxUint64(class, 2) for { c := time.After(*oDuration) factor := big.NewInt(0) factor.SetUint64(class) exp := big.NewInt(0) oneClass: for { select { case <-c: break oneClass default: } exp.Set(factor) factor.Lsh(factor, 1) factor.Add(factor, _1) if !factor.ProbablyPrime(pp) { continue } if !exp.ProbablyPrime(pp) { continue } if mathutil.ModPowBigInt(_2, exp, factor).Cmp(_1) != 0 { continue } if !factor.ProbablyPrime(pp2) { continue } if !exp.ProbablyPrime(pp2) { continue } fmt.Printf("%d: %s | M%s (%d bits)\n", class, factor, exp, factor.BitLen()) } class += 2 } }
func TestModPow(t *testing.T) { const N = 2e2 data := []struct{ b, e, m, r uint32 }{ {0, 1, 1, 0}, {0, 2, 1, 0}, {0, 3, 1, 0}, {1, 0, 1, 0}, {1, 1, 1, 0}, {1, 2, 1, 0}, {1, 3, 1, 0}, {2, 0, 1, 0}, {2, 1, 1, 0}, {2, 2, 1, 0}, {2, 3, 1, 0}, {2, 3, 4, 8}, {2, 3, 5, 4}, {2, 4, 3, 1}, {3, 3, 3, 3}, {3, 4, 5, 30}, } f := func(b, e, m uint32, expect *big.Int) { got := ModPow(b, e, m) if got.Cmp(expect) != 0 { t.Fatal(b, e, m, got, expect) } } var r big.Int for _, v := range data { r.SetInt64(int64(v.r)) f(v.b, v.e, v.m, &r) } rg, _ := mathutil.NewFC32(2, 1<<10, true) var bb big.Int for i := 0; i < N; i++ { b, e, m := uint32(rg.Next()), uint32(rg.Next()), uint32(rg.Next()) bb.SetInt64(int64(b)) f(b, e, m, mathutil.ModPowBigInt(&bb, New(e), New(m))) } }
func getClientProof(user string, password string, salt []byte, keyA *big.Int, keyB *big.Int, keya *big.Int) (keyM []byte, keyK []byte) { // M = H(H(N) xor H(g), H(I), s, A, B, K) prime, g, _ := getPrime() keyK = getClientSession(user, password, salt, keyA, keyB, keya) n1 := bytesToBig(bigToSha1(prime)) n2 := bytesToBig(bigToSha1(g)) n3 := mathutil.ModPowBigInt(n1, n2, prime) n4 := getStringHash(user) sha1 := sha1.New() sha1.Write(n3.Bytes()) sha1.Write(n4.Bytes()) sha1.Write(salt) sha1.Write(keyA.Bytes()) sha1.Write(keyB.Bytes()) sha1.Write(keyK) keyM = sha1.Sum(nil) return keyM, keyK }
// HasFactorBigInt returns true if d | Mn, d > 0. Typical run time for a 128 // bit factor and a 32 bit exponent is < 75 µs. func HasFactorBigInt(d *big.Int, n uint32) bool { return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && mathutil.ModPowBigInt(_2, big.NewInt(int64(n)), d).Cmp(_1) == 0 }
// HasFactorBigInt2 returns true if d | Mn, d > 0 func HasFactorBigInt2(d, n *big.Int) bool { return d.Cmp(_1) == 0 || d.Sign() > 0 && d.Bit(0) == 1 && mathutil.ModPowBigInt(_2, n, d).Cmp(_1) == 0 }
func getVerifier(user string, password string, salt []byte) *big.Int { prime, g, _ := getPrime() x := getUserHash(salt, user, password) return mathutil.ModPowBigInt(g, x, prime) }