ecdsa: avoid some big.Int conversion
This commit is contained in:
37
crypto/internal/asn1.go
Normal file
37
crypto/internal/asn1.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// Taken from crypto/ecdsa
|
||||
|
||||
func EncodeSignatureToASN1(r, s []byte) ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
addASN1IntBytes(b, r)
|
||||
addASN1IntBytes(b, s)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// addASN1IntBytes encodes in ASN.1 a positive integer represented as
|
||||
// a big-endian byte slice with zero or more leading zeroes.
|
||||
func addASN1IntBytes(b *cryptobyte.Builder, bytes []byte) {
|
||||
for len(bytes) > 0 && bytes[0] == 0 {
|
||||
bytes = bytes[1:]
|
||||
}
|
||||
if len(bytes) == 0 {
|
||||
b.SetError(errors.New("invalid integer"))
|
||||
return
|
||||
}
|
||||
b.AddASN1(asn1.INTEGER, func(c *cryptobyte.Builder) {
|
||||
if bytes[0]&0x80 != 0 {
|
||||
c.AddUint8(0)
|
||||
}
|
||||
c.AddBytes(bytes)
|
||||
})
|
||||
}
|
||||
@@ -34,11 +34,17 @@ func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
||||
}
|
||||
|
||||
// PublicKeyFromXY converts x and y coordinates into a PublicKey.
|
||||
func PublicKeyFromXY(x, y *big.Int) (*PublicKey, error) {
|
||||
if !elliptic.P256().IsOnCurve(x, y) {
|
||||
func PublicKeyFromXY(x, y []byte) (*PublicKey, error) {
|
||||
pub := &PublicKey{k: &ecdsa.PublicKey{
|
||||
Curve: elliptic.P256(),
|
||||
X: new(big.Int).SetBytes(x),
|
||||
Y: new(big.Int).SetBytes(y),
|
||||
}}
|
||||
|
||||
if !elliptic.P256().IsOnCurve(pub.k.X, pub.k.Y) {
|
||||
return nil, fmt.Errorf("invalid P-256 public key")
|
||||
}
|
||||
return &PublicKey{k: &ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y}}, nil
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromPublicKeyMultibase decodes the public key from its Multibase form
|
||||
@@ -128,13 +134,14 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Hash the message with SHA-256
|
||||
hash := sha256.Sum256(message)
|
||||
// For some reason, the go crypto library in ecdsa.Verify() encodes the signature as ASN.1 to then decode it.
|
||||
// This means it's actually more efficient to encode the signature as ASN.1 here.
|
||||
sigAsn1, err := helpers.EncodeSignatureToASN1(signature[:SignatureBytesSize/2], signature[SignatureBytesSize/2:])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(signature[:SignatureBytesSize/2])
|
||||
s := new(big.Int).SetBytes(signature[SignatureBytesSize/2:])
|
||||
|
||||
return ecdsa.Verify(p.k, hash[:], r, s)
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
|
||||
@@ -34,11 +34,17 @@ func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
||||
}
|
||||
|
||||
// PublicKeyFromXY converts x and y coordinates into a PublicKey.
|
||||
func PublicKeyFromXY(x, y *big.Int) (*PublicKey, error) {
|
||||
if !elliptic.P384().IsOnCurve(x, y) {
|
||||
func PublicKeyFromXY(x, y []byte) (*PublicKey, error) {
|
||||
pub := &PublicKey{k: &ecdsa.PublicKey{
|
||||
Curve: elliptic.P384(),
|
||||
X: new(big.Int).SetBytes(x),
|
||||
Y: new(big.Int).SetBytes(y),
|
||||
}}
|
||||
|
||||
if !elliptic.P384().IsOnCurve(pub.k.X, pub.k.Y) {
|
||||
return nil, fmt.Errorf("invalid P-384 public key")
|
||||
}
|
||||
return &PublicKey{k: &ecdsa.PublicKey{Curve: elliptic.P384(), X: x, Y: y}}, nil
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromPublicKeyMultibase decodes the public key from its Multibase form
|
||||
@@ -128,13 +134,14 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Hash the message with SHA-384
|
||||
hash := sha512.Sum384(message)
|
||||
// For some reason, the go crypto library in ecdsa.Verify() encodes the signature as ASN.1 to then decode it.
|
||||
// This means it's actually more efficient to encode the signature as ASN.1 here.
|
||||
sigAsn1, err := helpers.EncodeSignatureToASN1(signature[:SignatureBytesSize/2], signature[SignatureBytesSize/2:])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(signature[:SignatureBytesSize/2])
|
||||
s := new(big.Int).SetBytes(signature[SignatureBytesSize/2:])
|
||||
|
||||
return ecdsa.Verify(p.k, hash[:], r, s)
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
|
||||
@@ -34,11 +34,17 @@ func PublicKeyFromBytes(b []byte) (*PublicKey, error) {
|
||||
}
|
||||
|
||||
// PublicKeyFromXY converts x and y coordinates into a PublicKey.
|
||||
func PublicKeyFromXY(x, y *big.Int) (*PublicKey, error) {
|
||||
if !elliptic.P521().IsOnCurve(x, y) {
|
||||
func PublicKeyFromXY(x, y []byte) (*PublicKey, error) {
|
||||
pub := &PublicKey{k: &ecdsa.PublicKey{
|
||||
Curve: elliptic.P521(),
|
||||
X: new(big.Int).SetBytes(x),
|
||||
Y: new(big.Int).SetBytes(y),
|
||||
}}
|
||||
|
||||
if !elliptic.P521().IsOnCurve(pub.k.X, pub.k.Y) {
|
||||
return nil, fmt.Errorf("invalid P-521 public key")
|
||||
}
|
||||
return &PublicKey{k: &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y}}, nil
|
||||
return pub, nil
|
||||
}
|
||||
|
||||
// PublicKeyFromPublicKeyMultibase decodes the public key from its Multibase form
|
||||
@@ -128,13 +134,14 @@ func (p *PublicKey) VerifyBytes(message, signature []byte) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Hash the message with SHA-512
|
||||
hash := sha512.Sum512(message)
|
||||
// For some reason, the go crypto library in ecdsa.Verify() encodes the signature as ASN.1 to then decode it.
|
||||
// This means it's actually more efficient to encode the signature as ASN.1 here.
|
||||
sigAsn1, err := helpers.EncodeSignatureToASN1(signature[:SignatureBytesSize/2], signature[SignatureBytesSize/2:])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
r := new(big.Int).SetBytes(signature[:SignatureBytesSize/2])
|
||||
s := new(big.Int).SetBytes(signature[SignatureBytesSize/2:])
|
||||
|
||||
return ecdsa.Verify(p.k, hash[:], r, s)
|
||||
return p.VerifyASN1(message, sigAsn1)
|
||||
}
|
||||
|
||||
func (p *PublicKey) VerifyASN1(message, signature []byte) bool {
|
||||
|
||||
Reference in New Issue
Block a user