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()) }
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 }
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) } } }
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) }