Ejemplo n.º 1
0
func recoverKey(sigA, sigB *btcec.Signature, hashA, hashB []byte, pubKey *btcec.PublicKey) *btcec.PrivateKey {
	// Sanity checks
	if sigA.R.Cmp(sigB.R) != 0 {
		log.Println("Different R!")
		return nil
	}
	if !ecdsa.Verify(pubKey.ToECDSA(), hashA, sigA.R, sigA.S) {
		log.Println("A fails to verify!")
		return nil
	}
	if !ecdsa.Verify(pubKey.ToECDSA(), hashB, sigB.R, sigB.S) {
		log.Println("B fails to verify!")
		return nil
	}
	if !reflect.DeepEqual(pubKey.Curve, btcec.S256()) {
		log.Println("What the curve?!")
		return nil
	}

	c := btcec.S256()

	N := c.Params().N
	zA := hashToInt(hashA, c)
	zB := hashToInt(hashB, c)

	sDiffInv := new(big.Int).Sub(sigA.S, sigB.S)
	sDiffInv.Mod(sDiffInv, N)
	sDiffInv.ModInverse(sDiffInv, N)

	zDiff := new(big.Int).Sub(zA, zB)
	zDiff.Mod(zDiff, N)

	k := new(big.Int).Mul(zDiff, sDiffInv)
	k.Mod(k, N)

	rInv := new(big.Int).ModInverse(sigA.R, N)

	D := new(big.Int)
	D.Mul(sigA.S, k)
	D.Sub(D, zA)
	D.Mul(D, rInv)
	D.Mod(D, N)

	x, y := c.ScalarBaseMult(D.Bytes())
	if pubKey.X.Cmp(x) != 0 {
		log.Println("X!")
		return nil
	}
	if pubKey.Y.Cmp(y) != 0 {
		log.Println("Y!")
		return nil
	}

	return &btcec.PrivateKey{
		PublicKey: ecdsa.PublicKey{
			Curve: c,
			X:     x,
			Y:     y,
		},
		D: D,
	}
}