func main() { i := 1 n := big.NewInt(1) q := big.NewInt(0) p, err := cache.BaseExp(10, 99999999) if err != nil { panic(err) } l := p.BitLen() fmt.Printf("LEN: %10d\n", l) for q = range sieve.BigSieve() { n.Mul(n, q) if i < 1000000 { // Skip ahead. For small numbers, console output is the bottleneck. i++ continue } c := n.BitLen() fmt.Printf("\rLEN: %10d %d", c, i) if c > l { // It looks like we've found our number! fmt.Println() break } i++ } }
func FromBabelianAddressCompressed(input []byte) []byte { var ret bytes.Buffer inputBuf := bytes.NewBuffer(input) zipper, err := gzip.NewReader(inputBuf) if err != nil { fmt.Println("Error: ", err) } defer zipper.Close() dec := gob.NewDecoder(zipper) var pages []Page err = dec.Decode(&pages) if err != nil { fmt.Println("Decode error: ", err) } for _, pagestr := range pages { hex := pagestr.Hex wall := pagestr.Wall shelf := pagestr.Shelf volume := pagestr.Volume page := pagestr.Page loc_int := big.NewInt(0).Add(page, big.NewInt(0).Add(volume, big.NewInt(0).Add(shelf, wall))) multed := big.NewInt(0).Mul(loc_int, loc_mult) key := big.NewInt(0).Sub(hex, multed) ret.Write(key.Bytes()) } return ret.Bytes() }
func pairwiseThread(start, step int, wg *sync.WaitGroup, moduli []*gmp.Int, collisions chan<- Collision) { gcd := gmp.NewInt(0) for i := start; i < len(moduli); i += step { for j := i + 1; j < len(moduli); j++ { m1 := moduli[i] m2 := moduli[j] if m1.Cmp(m2) == 0 { collisions <- Collision{Modulus: m1} } else if gcd.GCD(nil, nil, m1, m2).BitLen() != 1 { // There's only one number with a BitLen of 1 q := gmp.NewInt(0) q.Quo(m1, gcd) collisions <- Collision{ Modulus: m1, P: gcd, Q: q, } q = gmp.NewInt(0) q.Quo(m2, gcd) collisions <- Collision{ Modulus: m2, P: gcd, Q: q, } gcd = gmp.NewInt(0) // Old gcd var can't be overwritten } } } wg.Done() }
func findGCD(wg *sync.WaitGroup, moduli []*gmp.Int, i int, collisions chan<- Collision) { m := moduli[i] q := gmp.NewInt(0) gcd := gmp.NewInt(0) for j := 0; j < i; j++ { n := moduli[j] if gcd.GCD(nil, nil, m, n).BitLen() != 1 { q.Quo(m, gcd) collisions <- Collision{ Modulus: m, P: gcd, Q: q, } q = gmp.NewInt(0) q.Quo(n, gcd) collisions <- Collision{ Modulus: n, P: gcd, Q: q, } q = gmp.NewInt(0) gcd = gmp.NewInt(0) } } wg.Done() }
// Just like Split, but return an error when receiving a kill signal from t. func splitOrQuit(z *big.Int, quit <-chan time.Time) (p, q *big.Int, err error) { q, r := big.NewInt(0), big.NewInt(0) if z.Sign() == 0 { return } max := roughSqrt(z) primes := sieve.BigSieve() for { select { case <-quit: err = ErrTimeout return case p = <-primes: if q.DivMod(z, p, r); r.Sign() == 0 { return } if max.Cmp(p) == -1 { q.SetInt64(1) p.Set(z) return } } } return }
// Tests the candidate (i) against all other moduli func findDivisors(wg *sync.WaitGroup, moduli []*gmp.Int, i int, gcd *gmp.Int, collisions chan<- Collision) { m := moduli[i] q := gmp.NewInt(0) r := gmp.NewInt(0) q.Quo(m, gcd) collisions <- Collision{ Modulus: m, P: gcd, Q: q, } q = gmp.NewInt(0) for j := 0; j < i; j++ { n := moduli[j] q.QuoRem(n, gcd, r) if r.BitLen() == 0 { collisions <- Collision{ Modulus: n, P: gcd, Q: q, } } q = gmp.NewInt(0) } wg.Done() }
// Make a n digit number func nDigitNumberGmp(digits int64) *gmp.Int { x := gmp.NewInt(10) n := gmp.NewInt(digits) one := gmp.NewInt(1) x.Exp(x, n, nil) x.Sub(x, one) return x }
// Modder creates a generator that yields remainders of z for each prime. func Modder(z *big.Int) *modder { return &modder{ z: z, q: big.NewInt(1), r: big.NewInt(0), t: big.NewInt(0), sieve: sieve.BigSieve(), } }
// BaseExpShiftK returns b^(e+s)+k. func BaseExpShiftK(b, e, s, k int64) (z *big.Int, err error) { if z, err = BaseExp(b, e); err == nil { sh := big.NewInt(b) sh.Exp(sh, big.NewInt(abs(s)), nil) if s > 0 { z.Mul(z, sh) } else if s != 0 { z.Div(z, sh) } z.Add(z, big.NewInt(k)) } return }
// BigSieve generates prime numbers as *big.Int. func BigSieve() (ch chan *big.Int) { ch = make(chan *big.Int) go func() { for p := range Sieve() { ch <- big.NewInt(int64(p)) } }() return }
func benchmarkGmpMulN(b *testing.B, digits int64) { x := nDigitNumberGmp(digits) y := nDigitNumberGmp(digits) z := gmp.NewInt(0) b.ResetTimer() b.StartTimer() for i := b.N - 1; i >= 0; i-- { z.Mul(x, y) } }
// BaseExp returns b^e. func BaseExp(b, e int64) (z *big.Int, err error) { z = big.NewInt(b) filename := filepath.Join(cacheDir, fmt.Sprintf("%d_%d.gob", b, e)) if err = os.Mkdir(cacheDir, 0755); err != nil && !os.IsExist(err) { return } file, err := os.Open(filename) if err == nil { var b []byte if b, err = ioutil.ReadAll(file); err == nil { err = z.GobDecode(b) } return } if !os.IsNotExist(err) { return } z.Exp(z, big.NewInt(e), nil) err = cache(z, filename) return }
// This performs the GCD of the product of all previous moduli with the current one. // This uses around double the memory (minus quite a lot of overhead), and identifies // problematic input in O(n) time, but has to do another O(n) scan for each collision // to figure get the private key back. // If there are no collisions, this algorithm isn't parallel at all. // If we get a GCD that is the same as the modulus, we do a manual scan for either colliding Q or identical moduli // If we get a GCD lower than the modulus, we have one private key, then do a manual scan for others. func MulAccumGCD(moduli []*gmp.Int, collisions chan<- Collision) { accum := gmp.NewInt(1) gcd := new(gmp.Int) var wg sync.WaitGroup for i, modulus := range moduli { gcd.GCD(nil, nil, accum, modulus) if gcd.BitLen() != 1 { wg.Add(1) if gcd.Cmp(modulus) == 0 { go findGCD(&wg, moduli, i, collisions) continue } else { go findDivisors(&wg, moduli, i, gcd, collisions) gcd = new(gmp.Int) } } accum.Mul(accum, modulus) } wg.Wait() close(collisions) }
package main import ( "bufio" "flag" "fmt" big "github.com/ncw/gmp" "os" "strconv" ) var n = 0 var silent = false var ( tmp1 = big.NewInt(0) tmp2 = big.NewInt(0) tmp3 = big.NewInt(0) y2 = big.NewInt(0) bigk = big.NewInt(0) numer = big.NewInt(1) accum = big.NewInt(0) denom = big.NewInt(1) ten = big.NewInt(10) ) func extract_digit() int64 { if numer.Cmp(accum) > 0 { return -1 }
// BaseExpK returns b^e+k. func BaseExpK(b, e, k int64) (z *big.Int, err error) { if z, err = BaseExp(b, e); err == nil { z.Add(z, big.NewInt(k)) } return }
// Rought square root of z. func roughSqrt(z *big.Int) *big.Int { return big.NewInt(0).Exp(big.NewInt(2), big.NewInt(int64((z.BitLen()+1)/2)), nil) }
along with this program. If not, see <http://www.gnu.org/licenses/>. */ package babel import ( "bytes" "compress/gzip" "encoding/gob" "fmt" big "github.com/ncw/gmp" "math/rand" "strings" "time" ) var length_of_page = big.NewInt(3239) var seededRandom = rand.New(rand.NewSource(time.Now().UnixNano())) var loc_mult = big.NewInt(0).Exp(big.NewInt(30), length_of_page, big.NewInt(0)) var tobabelreplacer = strings.NewReplacer( "0", "a", "1", "b", "2", "c", "3", "d", "4", "e", "5", "f", "6", "g", "7", "h", "8", "i", "9", "j", "a", "k", "b", "l",
func ToBabelianAddressCompressed(input []byte) []byte { nonbabel := bytes.NewBuffer(input) var pages []Page var blocks [][]byte var pagenum = int(float64(nonbabel.Len())/float64(3239)) + 1 for i := 0; i < pagenum; i++ { blocks = append(blocks, nonbabel.Next(3239)) } for _, subabel := range blocks { wall := big.NewInt(0).Rand(seededRandom, big.NewInt(4)) shelf := big.NewInt(0).Rand(seededRandom, big.NewInt(5)) volume := big.NewInt(0).Rand(seededRandom, big.NewInt(410)) page := big.NewInt(0).Rand(seededRandom, big.NewInt(410)) loc_int := big.NewInt(0).Add(page, big.NewInt(0).Add(volume, big.NewInt(0).Add(shelf, wall))) x := big.NewInt(0).SetBytes(subabel) multed := big.NewInt(0).Mul(loc_int, loc_mult) added := big.NewInt(0).Add(x, multed) pages = append(pages, Page{added, wall, shelf, volume, page}) } var network bytes.Buffer var output bytes.Buffer enc := gob.NewEncoder(&network) err := enc.Encode(pages) if err != nil { fmt.Println(err) } zipper := gzip.NewWriter(&output) _, err = zipper.Write(network.Bytes()) zipper.Close() if err != nil { fmt.Println("Error: ", err) } return output.Bytes() }