@@ -18,6 +18,8 @@ import (
1818var (
1919 errNegativeValue = errors .New ("value may be interpreted as negative" )
2020 errExcessivelyPaddedValue = errors .New ("value is excessively padded" )
21+ errHighS = errors .New ("signature is not canonical due to unnecessarily high S value" )
22+ errNoHeaderMagic = errors .New ("malformed signature: no header magic" )
2123)
2224
2325// Signature is a type representing an ecdsa signature.
@@ -90,7 +92,7 @@ func parseSig(sigStr []byte, der bool) (*Signature, error) {
9092 // 0x30
9193 index := 0
9294 if sigStr [index ] != 0x30 {
93- return nil , errors . New ( "malformed signature: no header magic" )
95+ return nil , errNoHeaderMagic
9496 }
9597 index ++
9698 // length of remaining message
@@ -254,3 +256,20 @@ func RecoverCompact(signature, hash []byte) (*btcec.PublicKey, bool, error) {
254256func Sign (key * btcec.PrivateKey , hash []byte ) * Signature {
255257 return secp_ecdsa .Sign (key , hash )
256258}
259+
260+ // VerifyLowS verifies that the given ECDSA signature is strictly DER-encoded
261+ // and uses a canonical low-S value. It returns nil if the signature is valid;
262+ // otherwise it returns the encountered error.
263+ func VerifyLowS (sigStr []byte ) error {
264+ sig , err := parseSig (sigStr , true )
265+ if err != nil {
266+ return err
267+ }
268+ sValue := sig .S ()
269+ if sValue .IsOverHalfOrder () {
270+ // High-S, s > N/2.
271+ return errHighS
272+ }
273+ // Low-S, s <= N/2.
274+ return nil
275+ }
0 commit comments