예제 #1
0
func main() {
	pi := new(big.Int)
	pi.SetString("7199773997391911030609999317773941274322764333428698921736339643928346453700085358802973900485592910475480089726140708102474957429903531369589969318716771", 10)
	gi := new(big.Int)
	gi.SetString("4565356397095740655436854503483826832136106141639563487732438195343690437606117828318042418238184896212352329118608100083187535033402010599512641674644143", 10)
	q := new(big.Int)
	q.SetString("236234353446506858198510045061214171961", 10)

	G := dh.NewFiniteGroup(*pi)
	g := dh.NewFiniteElement(G, *gi)
	GG := dh.NewGeneratedGroup(G, g, *q)
	d := dh.NewDiffieHellman(GG)

	factors := dh.FindCoFactors(q, pi, G)

	moduli := make(map[int64]int64)
	total := big.NewInt(1)

	for factor, h := range factors {
		total.Mul(total, big.NewInt(factor))
		mac := Bob(d, h)
		log.Printf("Guessing the shared secret in the subgroup of order %d", factor)
		found := false
		for i := int64(1); i <= factor; i++ {
			k := G.Pow(h, big.NewInt(i))
			if hmac.Equal(mac, Sign(secretMessage, k)) {
				//log.Printf("%d^%d", elt, i)
				found = true
				moduli[factor] = i
				break
			}
		}
		if !found {
			panic("Could not guess the shared secret")
		}
	}

	// From Wikipedia CRT page
	x := new(big.Int)
	for n, a := range moduli {
		N := new(big.Int).Set(total)
		N.Div(N, big.NewInt(n))
		N.ModInverse(N, big.NewInt(n))
		N.Mul(N, total)
		N.Div(N, big.NewInt(n))
		N.Mul(N, big.NewInt(a))
		x.Add(x, N)
		x.Mod(x, total)
	}
	log.Printf("Predicted key: %d", x)

	log.Printf("%s", d)
}
예제 #2
0
func main() {
	p, _ := new(big.Int).SetString("233970423115425145524320034830162017933", 10)
	a := big.NewInt(-95051)
	b := big.NewInt(11279326)
	G := dh.NewEllipticCurve(a, b, p)

	gx := big.NewInt(182)
	gy, _ := new(big.Int).SetString("85518893674295321206118380980485522083", 10)
	g := dh.NewEllipticCurveElement(G, gx, gy)
	q, _ := new(big.Int).SetString("29246302889428143187362802287225875743", 10)
	GG := dh.NewGeneratedGroup(G, g, *q)

	log.Printf("========== PART 1 ==========")
	alice := dh.NewECDSA(GG)
	log.Printf("Alice's group identity: %s", alice.Group().Identity())
	log.Printf("Alice's group generator: %s", alice.Group().Generator())
	log.Printf("Alice's generator^q: %s", alice.Group().Pow(alice.Group().Generator(), q))
	r, s := alice.Sign(secretMessage)
	log.Printf("r=%d s=%d", r, s)
	log.Printf("Verifies: %v",
		dh.ECDSAVerify(secretMessage, r, s, alice))
	log.Printf("Verifies with different message: %v",
		dh.ECDSAVerify([]byte("xxx"), r, s, alice))
	r.Add(r, big.NewInt(1))
	r.Mod(r, p)
	log.Printf("Verifies after r += 1: %v",
		dh.ECDSAVerify(secretMessage, r, s, alice))
	s.Add(s, big.NewInt(1))
	s.Mod(s, p)
	log.Printf("Verifies after r and s += 1: %v",
		dh.ECDSAVerify(secretMessage, r, s, alice))
	r.Sub(r, big.NewInt(1))
	r.Mod(r, p)
	log.Printf("Verifies after s += 1: %v",
		dh.ECDSAVerify(secretMessage, r, s, alice))
	s.Sub(s, big.NewInt(1))
	s.Mod(s, p)
	log.Printf("Verifies original: %v",
		dh.ECDSAVerify(secretMessage, r, s, alice))

	eve := dh.FindVerifyingECDSA(secretMessage, r, s, GG)
	log.Printf("Eve's group identity: %s", eve.Group().Identity())
	log.Printf("Eve's group generator: %s", eve.Group().Generator())
	log.Printf("Eve's generator^q: %s", eve.Group().Pow(eve.Group().Generator(), q))
	log.Printf("Eve verifies: %v",
		dh.ECDSAVerify(secretMessage, r, s, eve))

	log.Printf("========== PART 2 ==========")
	pi, err := crand.Prime(crand.Reader, keySize/2)
	if err != nil {
		panic(err)
	}
	qi, err := crand.Prime(crand.Reader, keySize/2)
	if err != nil {
		panic(err)
	}
	bob := dh.NewRSA(pi, qi)
	log.Printf("Bob's (N, e) = (%d, %d)", new(big.Int).Mul(qi, pi), bob.PublicKey())
	h := sha1.New()
	if n, err := h.Write(secretMessage); n != len(secretMessage) || err != nil {
		log.Fatal("Error calculating hash")
	}
	hashBytes := h.Sum(nil)
	// Don't feel like implementing padding again
	sigBytes := bob.Decrypt(new(big.Int).SetBytes(hashBytes))
	log.Printf("Bob's signature verifies: %v",
		hmac.Equal(hashBytes, bob.Encrypt(sigBytes).Bytes()))

	eveN, eveE, _ := chosenEncrytion(sigBytes, hashBytes, keySize)
	log.Printf("Eve's (N', e') = (%d, %d)", eveN, eveE)
	log.Printf("Eve's signature verifies: %v",
		hmac.Equal(hashBytes, new(big.Int).Exp(new(big.Int).SetBytes(sigBytes), eveE, eveN).Bytes()))

	log.Printf("========== PART 3 ==========")
	original := []byte("Transfer $100 from Chris to the Treasury")
	desired := []byte("Transfer $1,000,000 from the Treasury to Chris")
	pi, err = crand.Prime(crand.Reader, keySize/2)
	if err != nil {
		panic(err)
	}
	qi, err = crand.Prime(crand.Reader, keySize/2)
	if err != nil {
		panic(err)
	}
	bob = dh.NewRSA(pi, qi)
	log.Printf("Bob's (N, e) = (%d, %d)", new(big.Int).Mul(qi, pi), bob.PublicKey())
	enc := bob.Encrypt(original)
	eveN, eveE, eveD := chosenEncrytion(desired, enc.Bytes(), keySize)
	log.Printf("Eve's (N', e', d') = (%d, %d, %d)", eveN, eveE, eveD)
	if eveN.Cmp(new(big.Int).SetBytes(desired)) < 0 {
		log.Panic("Eve's key is too small")
	}
	log.Printf("Decrypted: %s", new(big.Int).Exp(enc, eveD, eveN).Bytes())
}
예제 #3
0
func main() {
	f, err := os.Create("/tmp/profile")
	if err != nil {
		log.Fatal(err)
	}
	pprof.StartCPUProfile(f)
	defer pprof.StopCPUProfile()

	p, _ := new(big.Int).SetString("233970423115425145524320034830162017933", 10)
	a := big.NewInt(-95051)
	b := big.NewInt(11279326)
	G := dh.NewEllipticCurve(a, b, p)

	gx := big.NewInt(182)
	gy, _ := new(big.Int).SetString("85518893674295321206118380980485522083", 10)
	g := dh.NewEllipticCurveElement(G, gx, gy)
	q, _ := new(big.Int).SetString("29246302889428143187362802287225875743", 10)
	GG := dh.NewGeneratedGroup(G, g, *q)

	var bias uint = 8
	alice := dh.NewBiasedECDSA(GG, bias)

	var msg = []byte("I was a fiend")
	key, _ := new(big.Int).SetString("255bf9c75628ab469b45cced58755a3", 16)
	d := new(big.Rat).SetInt(key)

	numSigs := 22
	B := dh.Matrix(make([]dh.Vector, numSigs+2))
	zero := dh.Vector(make([]*big.Rat, numSigs+2))
	for i, _ := range zero {
		zero[i] = new(big.Rat)
	}
	for i, _ := range B {
		B[i] = zero.Copy()
	}
	ct := big.NewRat(1, 1<<bias)
	B[len(B)-2][len(B)-2].Set(ct)
	cu := new(big.Rat).SetInt(q)
	cu.Quo(cu, big.NewRat(1<<bias, 1))
	B[len(B)-1][len(B)-1].Set(cu)
	ts := make([]*big.Int, numSigs)
	us := make([]*big.Int, numSigs)
	for i := 0; i < numSigs; i++ {
		B[i][i].SetInt(q)
		r, s := alice.Sign(msg)
		t, u := transform(msg, r, s, q, bias)
		dt := new(big.Int).Mul(key, t)
		temp := new(big.Int).Sub(u, dt)
		temp.Mod(temp, q)
		temp.Sub(q, temp)
		log.Printf("\ndt:     %x\nu:      %x\nq-u-dt: %x\nq:      %x", dt, u, temp, q)
		ts[i] = t
		us[i] = u
		B[len(B)-2][i] = new(big.Rat).SetInt(t)
		B[len(B)-1][i] = new(big.Rat).SetInt(u)
	}

	check := B[len(B)-1].Copy()
	check.Sub(B[len(B)-2].Copy().Scale(d))
	for i := 0; i < numSigs; i++ {
		t := ts[i]
		dt := new(big.Int).Mul(key, t)
		m := new(big.Int).Div(dt, q)
		check.Add(B[i].Copy().Scale(new(big.Rat).SetInt(m)))
	}
	log.Printf("check=%s", check)

	B.LLL(big.NewRat(99, 100))

	for _, v := range B {
		if v[len(v)-1].Cmp(cu) == 0 {
			log.Printf("%s", v)
			d := new(big.Rat)
			d.Sub(d, v[len(v)-2])
			d.Mul(d, big.NewRat(1<<bias, 1))
			guess := dh.Round(d).Num()
			log.Printf("Recovered key: %x", guess)
			log.Printf("Correct: %v", guess.Cmp(key) == 0)
		}
	}
}
예제 #4
0
func main() {
	p, _ := new(big.Int).SetString("233970423115425145524320034830162017933", 10)
	groupOrder, _ := new(big.Int).SetString("233970423115425145498902418297807005944", 10)
	a := big.NewInt(-95051)
	b := big.NewInt(11279326)
	EC := dh.NewEllipticCurve(a, b, p)
	gx := big.NewInt(182)
	gy, _ := new(big.Int).SetString("85518893674295321206118380980485522083", 10)
	g := dh.NewEllipticCurveElement(EC, gx, gy)

	MC := dh.NewMontgomeryCurve(big.NewInt(534), big.NewInt(1), p)
	mg := dh.NewMontgomeryCurveElement(MC, big.NewInt(4))
	q, _ := new(big.Int).SetString("29246302889428143187362802287225875743", 10)
	GG := dh.NewGeneratedGroup(MC, mg, *q)

	twistOrder := new(big.Int).Mul(p, big.NewInt(2))
	twistOrder.Add(twistOrder, big.NewInt(2))
	twistOrder.Sub(twistOrder, groupOrder)

	factors := dh.FindFactors(twistOrder, twistOrder, q, MC)

	total := big.NewInt(1)

	for factor, _ := range factors {
		total.Mul(total, big.NewInt(factor))
	}

	// Find an element that is order=total. We will use this to guess which
	// of the one or two remainders for each small prime is correct.
	log.Printf("Finding an element of order %d...", total)
	pow := new(big.Int)
	pow.Div(twistOrder, total)
	var h dh.Element = nil
	for {
		h = MC.Pow(MC.Random(), pow)
		if h.Cmp(MC.Identity()) != 0 {
			bad := false
			for factor, _ := range factors {
				if MC.Pow(h, big.NewInt(factor)).Cmp(MC.Identity()) == 0 {
					bad = true
					break
				}
			}
			if !bad {
				log.Printf("%s^%d == %s", h, total, MC.Pow(h, total))
				break
			}
		}
	}

	d := dh.NewDiffieHellman(GG)
	mac := Alice(d, h)

	// Determine the possible remainders for each small prime. There are usually
	// two because (u, v) and (u, -v) are conflated by the ladder.
	type factorModuli struct {
		factor         int64
		possibleModuli []int64
	}
	smallFactorModuli := make([]*factorModuli, 0)
	for factor, h := range factors {
		fm := &factorModuli{factor, make([]int64, 0)}
		mac := Alice(d, h)
		log.Printf("Guessing the shared secret in the subgroup of order %d", factor)
		found := false
		for i := int64(0); i < factor; i++ {
			k := MC.Pow(h, big.NewInt(i))
			if hmac.Equal(mac, Sign(secretMessage, k)) {
				found = true
				fm.possibleModuli = append(fm.possibleModuli, i)
				if i != 0 {
					// If h^i = (u, v) then (u, -v) = (h^i)^-1 = h^-i
					fm.possibleModuli = append(fm.possibleModuli, factor-i)
				}
				break
			}
		}
		if !found {
			log.Fatal("Could not guess the shared secret")
		}
		smallFactorModuli = append(smallFactorModuli, fm)
	}

	// Figure out which one of the various choices for each small remainder is correct.
	// For each permutation:
	//  - use CRT to compute remainder x mod "total"
	//  - check if the saved MAC corresponds to h^x.
	indices := make([]int, len(smallFactorModuli))
	bigModuli := make([]*big.Int, 0)
	for {
		carry := true
		for i := 0; carry && i < len(indices); i++ {
			indices[i] = (indices[i] + 1) % len(smallFactorModuli[i].possibleModuli)
			carry = indices[i] == 0
		}
		moduli := make(map[int64]int64)
		for i, fm := range smallFactorModuli {
			moduli[fm.factor] = fm.possibleModuli[indices[i]]
		}
		// From Wikipedia CRT page
		x := new(big.Int)
		for n, a := range moduli {
			N := new(big.Int).Set(total)
			N.Div(N, big.NewInt(n))
			N.ModInverse(N, big.NewInt(n))
			N.Mul(N, total)
			N.Div(N, big.NewInt(n))
			N.Mul(N, big.NewInt(a))
			x.Add(x, N)
			x.Mod(x, total)
		}
		k := MC.Pow(h, x)
		if hmac.Equal(mac, Sign(secretMessage, k)) {
			log.Printf("x mod r may be %s [r = %s]", x, total)
			bigModuli = append(bigModuli, x)
			if x.Cmp(new(big.Int)) != 0 {
				// Again there are probably two answers, because
				// h^x = h^-x using the montgomery ladder.
				y := new(big.Int).Sub(total, x)
				log.Printf("x mod r may be %s [r = %s]", y, total)
				bigModuli = append(bigModuli, y)
			}
			break
		}
	}

	// We now have two possible remainders mod "total". For each of those,
	// use the kangaroo algorithm to try to guess the secret. Note that
	// the public key that Alice gives us will *also* correspond to two
	// different points (u, v) and (u, -v) so we need to try plugging both
	// of them in and see which one works.
	ch := make(chan bool)
	for _, x := range bigModuli {
		for _, negate := range []bool{true, false} {
			go func(x *big.Int, negate bool) {
				n := new(big.Int)
				n.Sub(q, x)

				// Convert to Weierstrass form so Op is implemented and so
				// we can specify which of the two collapsed points (u, v)
				// and (u, -v) to use for this trial.
				w1 := dh.Q60MontgomeryToWeierstrass(d.PublicKey(), EC)
				if negate {
					dh.NegateWeierstrass(w1, EC)
				}
				w2 := EC.Pow(g, n)
				hp := EC.Op(w1, w2)
				gp := EC.Pow(g, total)
				B := new(big.Int)
				B.Div(q, total)

				log.Printf("Searching for index of %s in 0..%d", hp, B.Int64())
				m := dh.Pollard(EC, gp, hp, 0, int(B.Int64()))
				if m == nil {
					log.Printf("The wild kangaroo escaped!")
					return
				} else {
					m.Mod(m, q)
					log.Printf("index = %s", m)
					check := EC.Pow(gp, m)
					log.Printf("%s^%d mod %s = %s", gp, m, p, check)
					if check.Cmp(hp) != 0 {
						log.Printf("ERROR! Expected %s but got %s", hp, check)
					}
				}

				m.Mul(m, total)
				x.Add(x, m)

				log.Printf("Predicted key: %d", x)
				log.Printf("%s", d)
				ch <- true
			}(x, negate)
		}
	}

	<-ch
}
예제 #5
0
func main() {
	fmt.Printf("=== PHASE I: TEST ALGORITHM ===\n")
	pi := new(big.Int)
	pi.SetString("11470374874925275658116663507232161402086650258453896274534991676898999262641581519101074740642369848233294239851519212341844337347119899874391456329785623", 10)
	gi := new(big.Int)
	gi.SetString("622952335333961296978159266084741085889881358738459939978290179936063635566740258555167783009058567397963466103140082647486611657350811560630587013183357", 10)
	q := new(big.Int)
	q.SetString("335062023296420808191071248367701059461", 10)
	G := dh.NewFiniteGroup(*pi)
	g := dh.NewFiniteElement(G, *gi)
	GG := dh.NewGeneratedGroup(G, g, *q)

	targets := []string{
		"7760073848032689505395005705677365876654629189298052775754597607446617558600394076764814236081991643094239886772481052254010323780165093955236429914607119",
		"9388897478013399550694114614498790691034187453089355259602614074132918843899833277397448144245883225611726912025846772975325932794909655215329941809013733",
	}

	hi := new(big.Int)
	a := 0
	upperBounds := []int{1 << 20, 1 << 40}

	for i, hs := range targets {
		hi.SetString(hs, 10)
		b := upperBounds[i]

		h := dh.NewFiniteElement(G, *hi)

		log.Printf("Searching for discrete log of %s", h)
		x := dh.Pollard(GG, g, h, a, b)
		if x == nil {
			log.Printf("The wild kangaroo escaped!")
		} else {
			x.Mod(x, q)
			log.Printf("discrete log = %s", x)
			check := GG.Pow(g, x)
			log.Printf("%s^%d mod %s == %s", g, x, pi, GG.Pow(g, x))
			if check.Cmp(h) != 0 {
				log.Printf("ERROR! Expected %s but got %s", h, check)
			}
		}
	}

	fmt.Printf("\n=== PHASE II: APPLY WITH COFACTOR ATTACK ===\n")
	factors := dh.FindCoFactors(q, pi, G)

	moduli := make(map[int64]int64)
	total := big.NewInt(1)

	d := dh.NewDiffieHellman(GG)
	for factor, h := range factors {
		total.Mul(total, big.NewInt(factor))
		mac := Bob(d, h)
		log.Printf("Guessing the shared secret in the subgroup of order %d", factor)
		found := false
		for i := int64(1); i <= factor; i++ {
			k := G.Pow(h, big.NewInt(i))
			if hmac.Equal(mac, Sign(secretMessage, k)) {
				//log.Printf("%d^%d", elt, i)
				found = true
				moduli[factor] = i
				break
			}
		}
		if !found {
			panic("Could not guess the shared secret")
		}
	}

	// From Wikipedia CRT page
	x := new(big.Int)
	for n, a := range moduli {
		N := new(big.Int).Set(total)
		N.Div(N, big.NewInt(n))
		N.ModInverse(N, big.NewInt(n))
		N.Mul(N, total)
		N.Div(N, big.NewInt(n))
		N.Mul(N, big.NewInt(a))
		x.Add(x, N)
		x.Mod(x, total)
	}
	log.Printf("x mod r = %s [r = %s]", x, total)

	n := new(big.Int)
	n.Sub(q, x)

	hp := GG.Op(d.PublicKey(), GG.Pow(g, n))
	gp := GG.Pow(g, total)
	B := new(big.Int)
	B.Div(q, total)

	log.Printf("Searching for discrete log of %s", hp)
	m := dh.Pollard(GG, gp, hp, 0, int(B.Int64()))
	if m == nil {
		log.Printf("The wild kangaroo escaped!")
	} else {
		m.Mod(m, q)
		log.Printf("discrete log = %s", m)
		check := GG.Pow(gp, m)
		log.Printf("%s^%d mod %s == %s", gp, m, pi, GG.Pow(gp, m))
		if check.Cmp(hp) != 0 {
			log.Printf("ERROR! Expected %s but got %s", hp, check)
		}
	}

	m.Mul(m, total)
	x.Add(x, m)

	log.Printf("Predicted key: %d", x)
	log.Printf("%s", d)
}
예제 #6
0
func main() {
	p, _ := new(big.Int).SetString("233970423115425145524320034830162017933", 10)
	a := big.NewInt(-95051)
	//a.Sub(p, a)
	b := big.NewInt(11279326)
	G := dh.NewEllipticCurve(a, b, p)

	gx := big.NewInt(182)
	gy, _ := new(big.Int).SetString("85518893674295321206118380980485522083", 10)
	g := dh.NewEllipticCurveElement(G, gx, gy)
	q, _ := new(big.Int).SetString("29246302889428143187362802287225875743", 10)
	GG := dh.NewGeneratedGroup(G, g, *q)

	d1 := dh.NewDiffieHellman(GG)
	d2 := dh.NewDiffieHellman(GG)

	fmt.Printf("=== PHASE I: TEST DIFFIE-HELLMAN WORKS ===\n")

	log.Printf("Alice's DH: %s", d1)
	log.Printf("Bob's DH: %s", d2)

	log.Printf("Bob's shared secret from Alice's public key: %s", d2.SharedSecret(d1.PublicKey()))
	log.Printf("Alice's shared secret from Bob's public key: %s", d1.SharedSecret(d2.PublicKey()))

	fmt.Printf("=== PHASE II: BREAK DIFFIE-HELLMAN ===\n")

	weakSubgroups := []dh.Group{
		dh.NewEllipticCurve(big.NewInt(-95051), big.NewInt(210), p),
		dh.NewEllipticCurve(big.NewInt(-95051), big.NewInt(504), p),
		dh.NewEllipticCurve(big.NewInt(-95051), big.NewInt(727), p),
	}
	weakSubgroupOrders := make([]*big.Int, 3)
	weakSubgroupOrders[0], _ = new(big.Int).SetString("233970423115425145550826547352470124412", 10)
	weakSubgroupOrders[1], _ = new(big.Int).SetString("233970423115425145544350131142039591210", 10)
	weakSubgroupOrders[2], _ = new(big.Int).SetString("233970423115425145545378039958152057148", 10)

	allFactors := make(map[int64]dh.Element)

	for i, SG := range weakSubgroups {
		order := weakSubgroupOrders[i]
		factors := dh.FindFactors(order, order, q, SG)
		for factor, h := range factors {
			if _, ok := allFactors[factor]; !ok {
				allFactors[factor] = h
			}
		}
	}

	moduli := make(map[int64]int64)
	total := big.NewInt(1)

	d := dh.NewDiffieHellman(GG)
	for factor, h := range allFactors {
		mac := Bob(d, h)
		log.Printf("Guessing the shared secret in the subgroup of order %d", factor)
		found := false
		for i := int64(1); i <= factor; i++ {
			k := G.Pow(h, big.NewInt(i))
			if hmac.Equal(mac, Sign(secretMessage, k)) {
				found = true
				moduli[factor] = i
				break
			}
		}
		if found {
			total.Mul(total, big.NewInt(factor))
			if total.Cmp(q) > 0 {
				log.Printf("Found enough moduli")
				break
			}
		} else {
			// This can happen if a prime factor of one of the weak subgroups' order
			// is a double divisor in another one's order.
			log.Printf("Could not guess the shared secret!")
		}
	}

	// From Wikipedia CRT page
	x := new(big.Int)
	for n, a := range moduli {
		N := new(big.Int).Set(total)
		N.Div(N, big.NewInt(n))
		N.ModInverse(N, big.NewInt(n))
		N.Mul(N, total)
		N.Div(N, big.NewInt(n))
		N.Mul(N, big.NewInt(a))
		x.Add(x, N)
		x.Mod(x, total)
	}
	log.Printf("Predicted key: %d", x)

	log.Printf("%s", d)
}