// Verifies a hash using DER encoded signature func verifyECDSA(pubKey, signature, hash []byte) (bool, error) { sig, err := btcec.ParseDERSignature(signature, btcec.S256()) if err != nil { return false, err } pk, err := btcec.ParsePubKey(pubKey, btcec.S256()) if err != nil { return false, nil } return sig.Verify(hash, pk), nil }
func (pubKey PubKeySecp256k1) VerifyBytes(msg []byte, sig_ Signature) bool { pub__, err := secp256k1.ParsePubKey(append([]byte{0x04}, pubKey[:]...), secp256k1.S256()) if err != nil { return false } sig, ok := sig_.(SignatureSecp256k1) if !ok { return false } sig__, err := secp256k1.ParseDERSignature(sig[:], secp256k1.S256()) if err != nil { return false } return sig__.Verify(Sha256(msg), pub__) }
func TestSignatures(t *testing.T) { for _, test := range signatureTests { var err error if test.der { _, err = btcec.ParseDERSignature(test.sig, btcec.S256()) } else { _, err = btcec.ParseSignature(test.sig, btcec.S256()) } if err != nil { if test.isValid { t.Errorf("%s signature failed when shouldn't %v", test.name, err) } /* else { t.Errorf("%s got error %v", test.name, err) } */ continue } if !test.isValid { t.Errorf("%s counted as valid when it should fail", test.name) } } }
// mergeMultiSig combines the two signature scripts sigScript and prevScript // that both provide signatures for pkScript in output idx of tx. addresses // and nRequired should be the results from extracting the addresses from // pkScript. Since this function is internal only we assume that the arguments // have come from other functions internally and thus are all consistent with // each other, behaviour is undefined if this contract is broken. func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []btcutil.Address, nRequired int, pkScript, sigScript, prevScript []byte) []byte { // This is an internal only function and we already parsed this script // as ok for multisig (this is how we got here), so if this fails then // all assumptions are broken and who knows which way is up? pkPops, _ := parseScript(pkScript) sigPops, err := parseScript(sigScript) if err != nil || len(sigPops) == 0 { return prevScript } prevPops, err := parseScript(prevScript) if err != nil || len(prevPops) == 0 { return sigScript } // Convenience function to avoid duplication. extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte { for _, pop := range pops { if len(pop.data) != 0 { sigs = append(sigs, pop.data) } } return sigs } possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops)) possibleSigs = extractSigs(sigPops, possibleSigs) possibleSigs = extractSigs(prevPops, possibleSigs) // Now we need to match the signatures to pubkeys, the only real way to // do that is to try to verify them all and match it to the pubkey // that verifies it. we then can go through the addresses in order // to build our script. Anything that doesn't parse or doesn't verify we // throw away. addrToSig := make(map[string][]byte) sigLoop: for _, sig := range possibleSigs { // can't have a valid signature that doesn't at least have a // hashtype, in practise it is even longer than this. but // that'll be checked next. if len(sig) < 1 { continue } tSig := sig[:len(sig)-1] hashType := SigHashType(sig[len(sig)-1]) pSig, err := btcec.ParseDERSignature(tSig, btcec.S256()) if err != nil { continue } // We have to do this each round since hash types may vary // between signatures and so the hash will vary. We can, // however, assume no sigs etc are in the script since that // would make the transaction nonstandard and thus not // MultiSigTy, so we just need to hash the full thing. hash := calcSignatureHash(pkPops, hashType, tx, idx) for _, addr := range addresses { // All multisig addresses should be pubkey addresses // it is an error to call this internal function with // bad input. pkaddr := addr.(*btcutil.AddressPubKey) pubKey := pkaddr.PubKey() // If it matches we put it in the map. We only // can take one signature per public key so if we // already have one, we can throw this away. if pSig.Verify(hash, pubKey) { aStr := addr.EncodeAddress() if _, ok := addrToSig[aStr]; !ok { addrToSig[aStr] = sig } continue sigLoop } } } // Extra opcode to handle the extra arg consumed (due to previous bugs // in the reference implementation). builder := NewScriptBuilder().AddOp(OP_FALSE) doneSigs := 0 // This assumes that addresses are in the same order as in the script. for _, addr := range addresses { sig, ok := addrToSig[addr.EncodeAddress()] if !ok { continue } builder.AddData(sig) doneSigs++ if doneSigs == nRequired { break } } // padding for missing ones. for i := doneSigs; i < nRequired; i++ { builder.AddOp(OP_0) } script, _ := builder.Script() return script }