Example #1
0
// sign a multisig transaction with a specific key
func multisig_sign() {
	tx := raw_tx_from_file(*rawtx)
	if tx == nil {
		println("ERROR: Cannot decode the raw multisig transaction")
		println("Always use -msign <addr> along with -raw multi2sign.txt")
		return
	}

	k := address_to_key(*multisign)
	if k == nil {
		println("You do not know a key for address", *multisign)
		return
	}

	for i := range tx.TxIn {
		ms, er := btc.NewMultiSigFromScript(tx.TxIn[i].ScriptSig)
		if er != nil {
			println("WARNING: Input", i, "- not multisig:", er.Error())
			continue
		}
		hash := tx.SignatureHash(ms.P2SH(), i, btc.SIGHASH_ALL)
		//fmt.Println("Input number", i, len(ms.Signatures), " - hash to sign:", hex.EncodeToString(hash))

		r, s, e := btc.EcdsaSign(k.Key, hash)
		if e != nil {
			println(e.Error())
			return
		}
		btcsig := &btc.Signature{HashType: 0x01}
		btcsig.R.Set(r)
		btcsig.S.Set(s)

		ms.Signatures = append(ms.Signatures, btcsig)
		tx.TxIn[i].ScriptSig = ms.Bytes()
	}

	// Now re-order the signatures as they shall be:
	multisig_reorder(tx)

	write_tx_file(tx)
}
Example #2
0
func multisig_sign() {
	tx := raw_tx_from_file(*rawtx)
	if tx == nil {
		println("ERROR: Cannot decode the raw multisig transaction")
		println("Always use -msign <addr> along with -raw multi2sign.txt")
		return
	}

	ad2s, e := btc.NewAddrFromString(*multisign)
	if e != nil {
		println("BTC addr:", e.Error())
		return
	}

	var privkey []byte
	//var compr bool

	for i := range publ_addrs {
		if publ_addrs[i].Hash160 == ad2s.Hash160 {
			privkey = priv_keys[i][:]
			//compr = compressed_key[i]
			break
		}
	}

	if privkey == nil {
		println("You do not know a key for address", ad2s.String())
		return
	}

	for i := range tx.TxIn {
		ms, er := btc.NewMultiSigFromScript(tx.TxIn[i].ScriptSig)
		if er != nil {
			println("WARNING: Input", i, "- not multisig:", er.Error())
			continue
		}
		hash := tx.SignatureHash(ms.P2SH(), i, btc.SIGHASH_ALL)
		//fmt.Println("Input number", i, len(ms.Signatures), " - hash to sign:", hex.EncodeToString(hash))

		r, s, e := btc.EcdsaSign(privkey, hash)
		if e != nil {
			println(e.Error())
			return
		}
		btcsig := &btc.Signature{HashType: 0x01}
		btcsig.R.Set(r)
		btcsig.S.Set(s)

		ms.Signatures = append(ms.Signatures, btcsig)
		tx.TxIn[i].ScriptSig = ms.Bytes()
	}

	// Now re-order the signatures as they shall be:
	for i := range tx.TxIn {
		ms, er := btc.NewMultiSigFromScript(tx.TxIn[i].ScriptSig)
		if er != nil {
			//println(er.Error())
			continue
		}
		hash := tx.SignatureHash(ms.P2SH(), i, btc.SIGHASH_ALL)
		//fmt.Println("Input number", i, " - hash to sign:", hex.EncodeToString(hash))
		//fmt.Println(" ... number of signatures:", len(ms.Signatures))

		var sigs []*btc.Signature
		for ki := range ms.PublicKeys {
			//pk := btc.NewPublicKey(ms.PublicKeys[ki])
			//fmt.Println(ki, hex.EncodeToString(ms.PublicKeys[ki]))
			var sig *btc.Signature
			for si := range ms.Signatures {
				if btc.EcdsaVerify(ms.PublicKeys[ki], ms.Signatures[si].Bytes(), hash) {
					//fmt.Println("Key number", ki, "has signature number", si)
					sig = ms.Signatures[si]
					break
				}
			}
			if sig != nil {
				sigs = append(sigs, sig)
			} else if *verbose {
				fmt.Println("WARNING: Key number", ki, "has no matching signature")
			}

			if !*allowextramsigns && uint(len(sigs)) >= ms.SigsNeeded {
				break
			}

		}

		if len(ms.Signatures) > len(sigs) {
			fmt.Println("WARNING: Some signatures are obsolete and will be removed", len(ms.Signatures), "=>", len(sigs))
		} else if len(ms.Signatures) < len(sigs) {
			fmt.Println("It appears that same key is re-used.", len(sigs)-len(ms.Signatures), "more signatures were added")
		}
		ms.Signatures = sigs
		tx.TxIn[i].ScriptSig = ms.Bytes()
	}

	write_tx_file(tx)
}
Example #3
0
// prepare a signed transaction
func sign_tx(tx *btc.Tx) (all_signed bool) {
	var multisig_done bool
	all_signed = true

	// go through each input
	for in := range tx.TxIn {
		if ms, _ := btc.NewMultiSigFromScript(tx.TxIn[in].ScriptSig); ms != nil {
			hash := tx.SignatureHash(ms.P2SH(), in, btc.SIGHASH_ALL)
			for ki := range ms.PublicKeys {
				k := public_to_key(ms.PublicKeys[ki])
				if k != nil {
					r, s, e := btc.EcdsaSign(k.Key, hash)
					if e != nil {
						println("ERROR in sign_tx:", e.Error())
						all_signed = false
					} else {
						btcsig := &btc.Signature{HashType: 0x01}
						btcsig.R.Set(r)
						btcsig.S.Set(s)

						ms.Signatures = append(ms.Signatures, btcsig)
						tx.TxIn[in].ScriptSig = ms.Bytes()
						multisig_done = true
					}
				}
			}
		} else {
			uo := getUO(&tx.TxIn[in].Input)
			if uo == nil {
				println("ERROR: Unkown input:", tx.TxIn[in].Input.String(), "- missing balance folder?")
				all_signed = false
				continue
			}
			adr := addr_from_pkscr(uo.Pk_script)
			if adr == nil {
				fmt.Println("WARNING: Don't know how to sign input number", in)
				fmt.Println(" Pk_script:", hex.EncodeToString(uo.Pk_script))
				all_signed = false
				continue
			}
			k := hash_to_key(adr.Hash160)
			if k == nil {
				fmt.Println("WARNING: You do not have key for", adr.String(), "at input", in)
				all_signed = false
				continue
			}
			er := tx.Sign(in, uo.Pk_script, btc.SIGHASH_ALL, k.BtcAddr.Pubkey, k.Key)
			if er != nil {
				fmt.Println("ERROR: Sign failed for input number", in, er.Error())
				all_signed = false
			}
		}
	}

	// reorder signatures if we signed any multisig inputs
	if multisig_done && !multisig_reorder(tx) {
		all_signed = false
	}

	if !all_signed {
		fmt.Println("WARNING: Not all the inputs have been signed")
	}

	return
}
Example #4
0
// this function signs either a message or a raw transaction hash
func sign_message() {
	var hash []byte

	if *signhash != "" {
		var er error
		hash, er = hex.DecodeString(*signhash)
		if er != nil {
			println("Incorrect content of -hash parameter")
			println(er.Error())
			return
		}
	}

	ad2s, e := btc.NewAddrFromString(*signaddr)
	if e != nil {
		println(e.Error())
		if *signhash != "" {
			println("Always use -sign <addr> along with -hash <msghash>")
		}
		return
	}

	var privkey []byte
	var compr bool

	for i := range publ_addrs {
		if publ_addrs[i].Hash160 == ad2s.Hash160 {
			privkey = priv_keys[i][:]
			compr = compressed_key[i]

			// Sign raw hash?
			if hash != nil {
				txsig := new(btc.Signature)
				txsig.HashType = 0x01
				r, s, e := btc.EcdsaSign(privkey, hash)
				if e != nil {
					println(e.Error())
					return
				}
				txsig.R.Set(r)
				txsig.S.Set(s)
				fmt.Println("PublicKey:", hex.EncodeToString(publ_addrs[i].Pubkey))
				fmt.Println(hex.EncodeToString(txsig.Bytes()))
				return
			}

			break
		}
	}
	if privkey == nil {
		println("You do not have a private key for", ad2s.String())
		return
	}

	var msg []byte
	if *message == "" {
		msg, _ = ioutil.ReadAll(os.Stdin)
	} else {
		msg = []byte(*message)
	}

	hash = make([]byte, 32)
	if litecoin {
		ltc.HashFromMessage(msg, hash)
	} else {
		btc.HashFromMessage(msg, hash)
	}

	btcsig := new(btc.Signature)
	var sb [65]byte
	sb[0] = 27
	if compr {
		sb[0] += 4
	}

	r, s, e := btc.EcdsaSign(privkey, hash)
	if e != nil {
		println(e.Error())
		return
	}
	btcsig.R.Set(r)
	btcsig.S.Set(s)

	rd := btcsig.R.Bytes()
	sd := btcsig.S.Bytes()
	copy(sb[1+32-len(rd):], rd)
	copy(sb[1+64-len(sd):], sd)

	rpk := btcsig.RecoverPublicKey(hash[:], 0)
	sa := btc.NewAddrFromPubkey(rpk.Bytes(compr), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}

	rpk = btcsig.RecoverPublicKey(hash[:], 1)
	sa = btc.NewAddrFromPubkey(rpk.Bytes(compr), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		sb[0]++
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}
	println("Something went wrong. The message has not been signed.")
}
Example #5
0
// this function signs either a message or a raw hash
func sign_message() {
	var hash []byte
	var signkey *btc.PrivateAddr

	signkey = address_to_key(*signaddr)
	if signkey == nil {
		println("You do not have a private key for", *signaddr)
		return
	}

	if *signhash != "" {
		hash, er := hex.DecodeString(*signhash)
		if er != nil {
			println("Incorrect content of -hash parameter")
			println(er.Error())
			return
		} else if len(hash) > 0 {
			txsig := new(btc.Signature)
			txsig.HashType = 0x01
			r, s, e := btc.EcdsaSign(signkey.Key, hash)
			if e != nil {
				println(e.Error())
				return
			}
			txsig.R.Set(r)
			txsig.S.Set(s)
			fmt.Println("PublicKey:", hex.EncodeToString(signkey.BtcAddr.Pubkey))
			fmt.Println(hex.EncodeToString(txsig.Bytes()))
			return
		}
	}

	var msg []byte
	if *message == "" {
		msg, _ = ioutil.ReadAll(os.Stdin)
	} else {
		msg = []byte(*message)
	}

	hash = make([]byte, 32)
	if litecoin {
		ltc.HashFromMessage(msg, hash)
	} else {
		btc.HashFromMessage(msg, hash)
	}

	btcsig := new(btc.Signature)
	var sb [65]byte
	sb[0] = 27
	if signkey.IsCompressed() {
		sb[0] += 4
	}

	r, s, e := btc.EcdsaSign(signkey.Key, hash)
	if e != nil {
		println(e.Error())
		return
	}
	btcsig.R.Set(r)
	btcsig.S.Set(s)

	rd := btcsig.R.Bytes()
	sd := btcsig.S.Bytes()
	copy(sb[1+32-len(rd):], rd)
	copy(sb[1+64-len(sd):], sd)

	rpk := btcsig.RecoverPublicKey(hash[:], 0)
	sa := btc.NewAddrFromPubkey(rpk.Bytes(signkey.IsCompressed()), signkey.BtcAddr.Version)
	if sa.Hash160 == signkey.BtcAddr.Hash160 {
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}

	rpk = btcsig.RecoverPublicKey(hash[:], 1)
	sa = btc.NewAddrFromPubkey(rpk.Bytes(signkey.IsCompressed()), signkey.BtcAddr.Version)
	if sa.Hash160 == signkey.BtcAddr.Hash160 {
		sb[0]++
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}
	println("Something went wrong. The message has not been signed.")
}