Simplified the API a bit.
Also simplified the guts.
This commit is contained in:
parent
94a733bbc3
commit
6a90f24967
5 changed files with 42 additions and 37 deletions
3
dsa.go
3
dsa.go
|
@ -2,6 +2,7 @@ package rfc6979
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
|
"hash"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
|
// 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
|
// to the byte-length of the subgroup. This function does not perform that
|
||||||
// truncation itself.
|
// truncation itself.
|
||||||
func SignDSA(priv *dsa.PrivateKey, hash []byte, alg HashFunc) (r, s *big.Int, err error) {
|
func SignDSA(priv *dsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) {
|
||||||
n := priv.Q.BitLen()
|
n := priv.Q.BitLen()
|
||||||
if n&7 != 0 {
|
if n&7 != 0 {
|
||||||
err = dsa.ErrInvalidPublicKey
|
err = dsa.ErrInvalidPublicKey
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package rfc6979
|
package rfc6979_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/dsa"
|
"crypto/dsa"
|
||||||
|
@ -6,14 +6,17 @@ import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"hash"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/codahale/rfc6979"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dsaFixture struct {
|
type dsaFixture struct {
|
||||||
name string
|
name string
|
||||||
key *dsaKey
|
key *dsaKey
|
||||||
alg HashFunc
|
alg func() hash.Hash
|
||||||
message string
|
message string
|
||||||
r, s string
|
r, s string
|
||||||
}
|
}
|
||||||
|
@ -239,7 +242,7 @@ func testDsaFixture(f *dsaFixture, t *testing.T) {
|
||||||
digest = digest[0:g]
|
digest = digest[0:g]
|
||||||
}
|
}
|
||||||
|
|
||||||
r, s, err := SignDSA(f.key.key, digest, f.alg)
|
r, s, err := rfc6979.SignDSA(f.key.key, digest, f.alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
35
ecdsa.go
35
ecdsa.go
|
@ -3,25 +3,10 @@ package rfc6979
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/elliptic"
|
"crypto/elliptic"
|
||||||
|
"hash"
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
// copied from crypto/ecdsa
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignECDSA signs an arbitrary length hash (which should be the result of
|
// SignECDSA signs an arbitrary length hash (which should be the result of
|
||||||
// hashing a larger message) using the private key, priv. It returns the
|
// hashing a larger message) using the private key, priv. It returns the
|
||||||
// signature as a pair of integers.
|
// signature as a pair of integers.
|
||||||
|
@ -29,7 +14,7 @@ func hashToInt(hash []byte, c elliptic.Curve) *big.Int {
|
||||||
// Note that FIPS 186-3 section 4.6 specifies that the hash should be truncated
|
// 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
|
// to the byte-length of the subgroup. This function does not perform that
|
||||||
// truncation itself.
|
// truncation itself.
|
||||||
func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg HashFunc) (r, s *big.Int, err error) {
|
func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg func() hash.Hash) (r, s *big.Int, err error) {
|
||||||
c := priv.PublicKey.Curve
|
c := priv.PublicKey.Curve
|
||||||
N := c.Params().N
|
N := c.Params().N
|
||||||
|
|
||||||
|
@ -53,3 +38,19 @@ func SignECDSA(priv *ecdsa.PrivateKey, hash []byte, alg HashFunc) (r, s *big.Int
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// copied from crypto/ecdsa
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package rfc6979
|
package rfc6979_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
@ -6,14 +6,17 @@ import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/sha512"
|
"crypto/sha512"
|
||||||
|
"hash"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/codahale/rfc6979"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ecdsaFixture struct {
|
type ecdsaFixture struct {
|
||||||
name string
|
name string
|
||||||
key *ecdsaKey
|
key *ecdsaKey
|
||||||
alg HashFunc
|
alg func() hash.Hash
|
||||||
message string
|
message string
|
||||||
r, s string
|
r, s string
|
||||||
}
|
}
|
||||||
|
@ -425,7 +428,7 @@ func testEcsaFixture(f *ecdsaFixture, t *testing.T) {
|
||||||
digest = digest[0:g]
|
digest = digest[0:g]
|
||||||
}
|
}
|
||||||
|
|
||||||
r, s, err := SignECDSA(f.key.key, digest, f.alg)
|
r, s, err := rfc6979.SignECDSA(f.key.key, digest, f.alg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
23
rfc6979.go
23
rfc6979.go
|
@ -22,11 +22,8 @@ import (
|
||||||
"math/big"
|
"math/big"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HashFunc is a function which provides a fresh Hash (e.g., sha256.New).
|
|
||||||
type HashFunc func() hash.Hash
|
|
||||||
|
|
||||||
// mac returns an HMAC of the given key and message.
|
// mac returns an HMAC of the given key and message.
|
||||||
func (alg HashFunc) mac(k, m, buf []byte) []byte {
|
func mac(alg func() hash.Hash, k, m, buf []byte) []byte {
|
||||||
h := hmac.New(alg, k)
|
h := hmac.New(alg, k)
|
||||||
h.Write(m)
|
h.Write(m)
|
||||||
return h.Sum(buf[:0])
|
return h.Sum(buf[:0])
|
||||||
|
@ -76,7 +73,7 @@ func bits2octets(in []byte, q *big.Int, qlen, rolen int) []byte {
|
||||||
var one = big.NewInt(1)
|
var one = big.NewInt(1)
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc6979#section-3.2
|
// https://tools.ietf.org/html/rfc6979#section-3.2
|
||||||
func generateSecret(q, x *big.Int, alg HashFunc, hash []byte, test func(*big.Int) bool) {
|
func generateSecret(q, x *big.Int, alg func() hash.Hash, hash []byte, test func(*big.Int) bool) {
|
||||||
qlen := q.BitLen()
|
qlen := q.BitLen()
|
||||||
holen := alg().Size()
|
holen := alg().Size()
|
||||||
rolen := (qlen + 7) >> 3
|
rolen := (qlen + 7) >> 3
|
||||||
|
@ -89,25 +86,25 @@ func generateSecret(q, x *big.Int, alg HashFunc, hash []byte, test func(*big.Int
|
||||||
k := bytes.Repeat([]byte{0x00}, holen)
|
k := bytes.Repeat([]byte{0x00}, holen)
|
||||||
|
|
||||||
// Step D
|
// Step D
|
||||||
k = alg.mac(k, append(append(v, 0x00), bx...), k)
|
k = mac(alg, k, append(append(v, 0x00), bx...), k)
|
||||||
|
|
||||||
// Step E
|
// Step E
|
||||||
v = alg.mac(k, v, v)
|
v = mac(alg, k, v, v)
|
||||||
|
|
||||||
// Step F
|
// Step F
|
||||||
k = alg.mac(k, append(append(v, 0x01), bx...), k)
|
k = mac(alg, k, append(append(v, 0x01), bx...), k)
|
||||||
|
|
||||||
// Step G
|
// Step G
|
||||||
v = alg.mac(k, v, v)
|
v = mac(alg, k, v, v)
|
||||||
|
|
||||||
// Step H
|
// Step H
|
||||||
for {
|
for {
|
||||||
// Step H1
|
// Step H1
|
||||||
t := make([]byte, 0)
|
var t []byte
|
||||||
|
|
||||||
// Step H2
|
// Step H2
|
||||||
for len(t) < qlen/8 {
|
for len(t) < qlen/8 {
|
||||||
v = alg.mac(k, v, v)
|
v = mac(alg, k, v, v)
|
||||||
t = append(t, v...)
|
t = append(t, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +113,7 @@ func generateSecret(q, x *big.Int, alg HashFunc, hash []byte, test func(*big.Int
|
||||||
if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret) {
|
if secret.Cmp(one) >= 0 && secret.Cmp(q) < 0 && test(secret) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
k = alg.mac(k, append(v, 0x00), k)
|
k = mac(alg, k, append(v, 0x00), k)
|
||||||
v = alg.mac(k, v, v)
|
v = mac(alg, k, v, v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue