55 lines
1.2 KiB
Go
55 lines
1.2 KiB
Go
|
package rfc6979
|
||
|
|
||
|
import (
|
||
|
"crypto/ecdsa"
|
||
|
"crypto/elliptic"
|
||
|
"math/big"
|
||
|
)
|
||
|
|
||
|
func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
|
||
|
orderBits := c.Params().N.BitLen()
|
||
|
orderBytes := (orderBits + 7) / 8
|
||
|
if len(hash) > orderBytes {
|
||
|
hash = hash[:orderBytes]
|
||
|
}
|
||
|
|
||
|
ret := new(big.Int).SetBytes(hash)
|
||
|
excess := len(hash)*8 - orderBits
|
||
|
if excess > 0 {
|
||
|
ret.Rsh(ret, uint(excess))
|
||
|
}
|
||
|
return ret
|
||
|
}
|
||
|
|
||
|
// Sign signs an arbitrary length hash (which should be the result of hashing a
|
||
|
// larger message) using the private key, priv. It returns the signature as a
|
||
|
// pair of integers.
|
||
|
//
|
||
|
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
|
||
|
// to the byte-length of the subgroup. This function does not perform that
|
||
|
// truncation itself.
|
||
|
func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg HashAlgorithm) (r, s *big.Int, err error) {
|
||
|
c := priv.PublicKey.Curve
|
||
|
N := c.Params().N
|
||
|
|
||
|
generateSecret(N, priv.D, alg, hash, func(k *big.Int) bool {
|
||
|
kInv := new(big.Int).ModInverse(k, N)
|
||
|
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
|
||
|
r.Mod(r, N)
|
||
|
|
||
|
if r.Sign() == 0 {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
e := hashToInt(hash, c)
|
||
|
s = new(big.Int).Mul(priv.D, r)
|
||
|
s.Add(s, e)
|
||
|
s.Mul(s, kInv)
|
||
|
s.Mod(s, N)
|
||
|
|
||
|
return s.Sign() != 0
|
||
|
})
|
||
|
|
||
|
return
|
||
|
}
|