Esempio n. 1
0
func FindStealthSecret(sa *btc.StealthAddr) (d []byte) {
	for i := range StealthSecrets {
		if bytes.Equal(btc.PublicFromPrivate(StealthSecrets[i], true), sa.ScanKey[:]) {
			return StealthSecrets[i]
		}
	}
	for i := range ArmedStealthSecrets {
		if bytes.Equal(btc.PublicFromPrivate(ArmedStealthSecrets[i], true), sa.ScanKey[:]) {
			return ArmedStealthSecrets[i]
		}
	}
	return
}
Esempio n. 2
0
func listarmkeys(p string) {
	if p != "seed" {
		if len(wallet.StealthSecrets) > 0 {
			fmt.Println("Persistent secret scan keys:")
			for i := range wallet.StealthSecrets {
				pk := btc.PublicFromPrivate(wallet.StealthSecrets[i], true)
				fmt.Print(" #", i, "  ", hex.EncodeToString(pk))
				if p == "addr" {
					fmt.Print("  ", btc.NewAddrFromPubkey(pk, btc.AddrVerPubkey(common.Testnet)).String())
				}
				fmt.Println()
			}
		} else {
			fmt.Println("You have no persistent secret scan keys")
		}
	}
	if p != "file" {
		if len(wallet.ArmedStealthSecrets) > 0 {
			fmt.Println("Volatile secret scan keys:")
			for i := range wallet.ArmedStealthSecrets {
				pk := btc.PublicFromPrivate(wallet.ArmedStealthSecrets[i], true)
				fmt.Print(" #", i, "  ", hex.EncodeToString(pk))
				if p == "addr" {
					fmt.Print("  ", btc.NewAddrFromPubkey(pk, btc.AddrVerPubkey(common.Testnet)).String())
				}
				if p == "save" {
					fn := common.GocoinHomeDir + "wallet/stealth/" + hex.EncodeToString(pk)
					if fi, er := os.Stat(fn); er == nil && fi.Size() >= 32 {
						fmt.Print("  already on disk")
					} else {
						ioutil.WriteFile(fn, wallet.ArmedStealthSecrets[i], 0600)
						fmt.Print("  saved")
					}
					sys.ClearBuffer(wallet.ArmedStealthSecrets[i])
				}
				fmt.Println()
			}
		} else {
			fmt.Println("You have no volatile secret scan keys")
		}
	}
	if p == "save" {
		wallet.ArmedStealthSecrets = nil
		wallet.FetchStealthKeys()
	}
}
Esempio n. 3
0
func arm_stealth(p string) {
	var buf, b2 [256]byte

	create := p != ""

	fmt.Print("Enter seed password of the stealth key (empty line to abort) : ")
	le := sys.ReadPassword(buf[:])
	if le <= 0 {
		fmt.Println("Aborted")
		return
	}
	if create {
		fmt.Print("Re-enter the seed password : ")
		l := sys.ReadPassword(b2[:])
		if l != le && !bytes.Equal(buf[:le], b2[:l]) {
			sys.ClearBuffer(buf[:le])
			sys.ClearBuffer(b2[:l])
			fmt.Println("The passwords you entered do not match")
			return
		}
	}

	nw := make([]byte, 32)
	btc.ShaHash(buf[:le], nw) // seed
	sys.ClearBuffer(buf[:le])
	btc.ShaHash(nw, nw) // 1st key
	wallet.ArmedStealthSecrets = append(wallet.ArmedStealthSecrets, nw)
	if create {
		fmt.Println("You have created a new stealth scan-key. Make sure to not forget this password!")
		pk := btc.PublicFromPrivate(nw, true)
		fmt.Println("Public hexdump:", hex.EncodeToString(pk))
		fmt.Println(" Go to your wallet machine and execute:")
		fmt.Println("   wallet -scankey", hex.EncodeToString(pk), "-prefix 0")
		fmt.Println("   (change the prefix to a different value if you want)")
	}
	fmt.Println("Stealth key number", len(wallet.ArmedStealthSecrets)-1, "has been stored in memory")
	fmt.Println("Reloading the current wallet...")
	usif.ExecUiReq(&usif.OneUiReq{Handler: func(p string) {
		wallet.LoadWallet(wallet.MyWallet.FileName)
	}})
	show_prompt = false
}
Esempio n. 4
0
// Generate a new stealth address
func new_stealth_address(prv_key []byte) {
	sk, er := hex.DecodeString(*scankey)
	if er != nil {
		println(er.Error())
		os.Exit(1)
	}
	if len(sk) != 33 || sk[0] != 2 && sk[0] != 3 {
		println("scankey must be a compressed public key (33 bytes long)")
		os.Exit(1)
	}

	if *prefix > 16 {
		if *prefix > 24 {
			fmt.Println("The stealth prefix cannot be bigger than 32", *prefix)
			os.Exit(1)
		}
		fmt.Println("WARNING: You chose a prifix length of", *prefix)
		fmt.Println("WARNING: Big prefixes endanger your anonymity.")
	}

	pub := btc.PublicFromPrivate(prv_key, true)
	if pub == nil {
		println("PublicFromPrivate error 2")
		os.Exit(1)
	}

	sa := new(btc.StealthAddr)
	sa.Version = btc.StealthAddressVersion(testnet)
	sa.Options = 0
	copy(sa.ScanKey[:], sk)
	sa.SpendKeys = make([][33]byte, 1)
	copy(sa.SpendKeys[0][:], pub)
	sa.Sigs = 1
	sa.Prefix = make([]byte, 1+(byte(*prefix)+7)>>3)
	if *prefix > 0 {
		sa.Prefix[0] = byte(*prefix)
		rand.Read(sa.Prefix[1:])
	}
	fmt.Println(sa.String())
}
Esempio n. 5
0
// load the content of the "balance/" folder
func load_balance(showbalance bool) {
	var unknownInputs, multisigInputs int
	f, e := os.Open("balance/unspent.txt")
	if e != nil {
		println(e.Error())
		return
	}
	rd := bufio.NewReader(f)
	for {
		l, _, e := rd.ReadLine()
		if len(l) == 0 && e != nil {
			break
		}
		if l[64] == '-' {
			txid := btc.NewUint256FromString(string(l[:64]))
			rst := strings.SplitN(string(l[65:]), " ", 2)
			vout, _ := strconv.ParseUint(rst[0], 10, 32)
			uns := new(btc.TxPrevOut)
			copy(uns.Hash[:], txid.Hash[:])
			uns.Vout = uint32(vout)
			lab := ""
			if len(rst) > 1 {
				lab = rst[1]
			}

			str := string(l)
			if sti := strings.Index(str, "_StealthC:"); sti != -1 {
				c, e := hex.DecodeString(str[sti+10 : sti+10+64])
				if e != nil {
					fmt.Println("ERROR at stealth", txid.String(), vout, e.Error())
				} else {
					// add a new key to the wallet
					sec := btc.DeriveNextPrivate(first_seed[:], c)
					is_stealth[len(priv_keys)] = true
					priv_keys = append(priv_keys, sec)
					labels = append(labels, lab)
					pub_key := btc.PublicFromPrivate(sec, true)
					publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub_key, AddrVerPubkey()))
					compressed_key = append(compressed_key, true) // stealth keys are always compressed
				}
			}

			if _, ok := loadedTxs[txid.Hash]; !ok {
				tf, _ := os.Open("balance/" + txid.String() + ".tx")
				if tf != nil {
					siz, _ := tf.Seek(0, os.SEEK_END)
					tf.Seek(0, os.SEEK_SET)
					buf := make([]byte, siz)
					tf.Read(buf)
					tf.Close()
					th := btc.Sha2Sum(buf)
					if bytes.Equal(th[:], txid.Hash[:]) {
						tx, _ := btc.NewTx(buf)
						if tx != nil {
							loadedTxs[txid.Hash] = tx
						} else {
							println("transaction is corrupt:", txid.String())
						}
					} else {
						println("transaction file is corrupt:", txid.String())
						os.Exit(1)
					}
				} else {
					println("transaction file not found:", txid.String())
					os.Exit(1)
				}
			}

			// Sum up all the balance and check if we have private key for this input
			uo := UO(uns)

			add_it := true

			if !btc.IsP2SH(uo.Pk_script) {
				fnd := false
				for j := range publ_addrs {
					if publ_addrs[j].Owns(uo.Pk_script) {
						fnd = true
						break
					}
				}

				if !fnd {
					if *onlvalid {
						add_it = false
					}
					if showbalance {
						unknownInputs++
						if *verbose {
							ss := uns.String()
							ss = ss[:8] + "..." + ss[len(ss)-12:]
							fmt.Println(ss, "does not belong to your wallet (cannot sign it)")
						}
					}
				}
			} else {
				if *onlvalid {
					add_it = false
				}
				if *verbose {
					ss := uns.String()
					ss = ss[:8] + "..." + ss[len(ss)-12:]
					fmt.Println(ss, "belongs to a multisig address")
				}
				multisigInputs++
			}

			if add_it {
				unspentOuts = append(unspentOuts, uns)
				unspentOutsLabel = append(unspentOutsLabel, lab)
				totBtc += UO(uns).Value
			}
		}
	}
	f.Close()
	fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n",
		float64(totBtc)/1e8, len(unspentOuts), multisigInputs)
	if showbalance {
		if unknownInputs > 0 {
			fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs)
		}
	}
}
Esempio n. 6
0
func load_others() {
	f, e := os.Open(RawKeysFilename)
	if e == nil {
		defer f.Close()
		td := bufio.NewReader(f)
		for {
			li, _, _ := td.ReadLine()
			if li == nil {
				break
			}
			if len(li) == 0 {
				continue
			}
			pk := strings.SplitN(strings.Trim(string(li), " "), " ", 2)
			if pk[0][0] == '#' {
				continue // Just a comment-line
			}

			pkb := btc.Decodeb58(pk[0])

			if pkb == nil {
				println("Decodeb58 failed:", pk[0])
				continue
			}

			if len(pkb) < 6 {
				println("Syntax error in the raw keys file:", pk[0])
				continue
			}

			if len(pkb) != 37 && len(pkb) != 38 {
				println(pk[0][:6], "has wrong key", len(pkb))
				println(hex.EncodeToString(pkb))
				continue
			}

			if pkb[0] != AddrVerSecret() {
				println(pk[0][:6], "has version", pkb[0], "while we expect", AddrVerSecret())
				fmt.Println("You may want to play with -t or -ltc switch")
				continue
			}

			var sh [32]byte
			var compr bool

			if len(pkb) == 37 {
				// old/uncompressed key
				sh = btc.Sha2Sum(pkb[0:33])
				if !bytes.Equal(sh[:4], pkb[33:37]) {
					println(pk[0][:6], "checksum error")
					continue
				}
				compr = false
			} else {
				if pkb[33] != 1 {
					println(pk[0][:6], "a key of length 38 bytes must be compressed")
					continue
				}

				sh = btc.Sha2Sum(pkb[0:34])
				if !bytes.Equal(sh[:4], pkb[34:38]) {
					println(pk[0][:6], "checksum error")
					continue
				}
				compr = true
			}

			key := pkb[1:33]
			pub := btc.PublicFromPrivate(key, compr)
			if pub == nil {
				println("PublicFromPrivate failed")
				os.Exit(1)
			}

			priv_keys = append(priv_keys, key)
			compressed_key = append(compressed_key, compr)
			publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub, AddrVerPubkey()))
			if len(pk) > 1 {
				labels = append(labels, pk[1])
			} else {
				labels = append(labels, fmt.Sprint("Other ", len(priv_keys)))
			}
		}
		if *verbose {
			fmt.Println(len(priv_keys), "keys imported from", RawKeysFilename)
		}
	} else {
		if *verbose {
			fmt.Println("You can also have some dumped (b58 encoded) priv keys in file", RawKeysFilename)
		}
	}
}
Esempio n. 7
0
// Get the secret seed and generate "keycnt" key pairs (both private and public)
func make_wallet() {
	var lab string

	load_others()

	seed_key := make([]byte, 32)
	if !getseed(seed_key) {
		os.Exit(0)
	}

	defer func() {
		sys.ClearBuffer(seed_key)
	}()

	switch waltype {
	case 1:
		lab = "TypA"
		println("WARNING: Wallet Type 1 is obsolete")

	case 2:
		lab = "TypB"
		if type2sec != "" {
			d, e := hex.DecodeString(type2sec)
			if e != nil {
				println("t2sec error:", e.Error())
				os.Exit(1)
			}
			type2_secret = d
		} else {
			type2_secret = make([]byte, 20)
			btc.RimpHash(seed_key, type2_secret)
		}

	case 3:
		lab = "TypC"

	default:
		println("ERROR: Unsupported wallet type", waltype)
		os.Exit(0)
	}

	if *verbose {
		fmt.Println("Generating", keycnt, "keys, version", AddrVerPubkey(), "...")
	}
	for i := uint(0); i < keycnt; {
		prv_key := make([]byte, 32)
		if waltype == 3 {
			btc.ShaHash(seed_key, prv_key)
			seed_key = append(seed_key, byte(i))
		} else if waltype == 2 {
			seed_key = btc.DeriveNextPrivate(seed_key, type2_secret)
			copy(prv_key, seed_key)
		} else {
			btc.ShaHash(seed_key, prv_key)
			copy(seed_key, prv_key)
		}
		priv_keys = append(priv_keys, prv_key)
		if *scankey != "" {
			new_stealth_address(prv_key)
			return
		}

		// for stealth keys
		if i == 0 {
			copy(first_seed[:], prv_key)
		}
		compressed_key = append(compressed_key, !uncompressed)
		pub := btc.PublicFromPrivate(prv_key, !uncompressed)
		if pub != nil {
			adr := btc.NewAddrFromPubkey(pub, AddrVerPubkey())

			if *pubkey != "" && *pubkey == adr.String() {
				fmt.Println("Public address:", adr.String())
				fmt.Println("Public hexdump:", hex.EncodeToString(pub))
				return
			}
			publ_addrs = append(publ_addrs, adr)
			labels = append(labels, fmt.Sprint(lab, " ", i+1))
			i++
		} else {
			println("PublicFromPrivate error 3")
		}
	}
	if *verbose {
		fmt.Println("Private keys re-generated")
	}
}