recovery.go raw

   1  package secp
   2  
   3  import (
   4  	"fmt"
   5  )
   6  
   7  // SignRecoverable creates a recoverable ECDSA signature
   8  func (c *Context) SignRecoverable(msg32 []byte, seckey []byte) (sig []byte, err error) {
   9  	if ecdsaSignRecoverable == nil {
  10  		err = fmt.Errorf("recovery module not available")
  11  		return
  12  	}
  13  
  14  	if len(msg32) != 32 {
  15  		err = fmt.Errorf("message must be 32 bytes")
  16  		return
  17  	}
  18  
  19  	if len(seckey) != PrivateKeySize {
  20  		err = fmt.Errorf("private key must be %d bytes", PrivateKeySize)
  21  		return
  22  	}
  23  
  24  	sig = make([]byte, RecoverableSignatureSize)
  25  	ret := ecdsaSignRecoverable(c.ctx, &sig[0], &msg32[0], &seckey[0], 0, 0)
  26  	if ret != 1 {
  27  		err = fmt.Errorf("failed to create recoverable signature")
  28  		return
  29  	}
  30  
  31  	return
  32  }
  33  
  34  // SerializeRecoverableSignatureCompact serializes a recoverable signature
  35  func (c *Context) SerializeRecoverableSignatureCompact(sig []byte) (output64 []byte, recid int32, err error) {
  36  	if ecdsaRecoverableSignatureSerializeCompact == nil {
  37  		err = fmt.Errorf("recovery module not available")
  38  		return
  39  	}
  40  
  41  	if len(sig) != RecoverableSignatureSize {
  42  		err = fmt.Errorf("recoverable signature must be %d bytes", RecoverableSignatureSize)
  43  		return
  44  	}
  45  
  46  	output64 = make([]byte, 64)
  47  	ret := ecdsaRecoverableSignatureSerializeCompact(c.ctx, &output64[0], &recid, &sig[0])
  48  	if ret != 1 {
  49  		err = fmt.Errorf("failed to serialize recoverable signature")
  50  		return
  51  	}
  52  
  53  	return
  54  }
  55  
  56  // ParseRecoverableSignatureCompact parses a compact recoverable signature
  57  func (c *Context) ParseRecoverableSignatureCompact(input64 []byte, recid int32) (sig []byte, err error) {
  58  	if ecdsaRecoverableSignatureParseCompact == nil {
  59  		err = fmt.Errorf("recovery module not available")
  60  		return
  61  	}
  62  
  63  	if len(input64) != 64 {
  64  		err = fmt.Errorf("compact signature must be 64 bytes")
  65  		return
  66  	}
  67  
  68  	if recid < 0 || recid > 3 {
  69  		err = fmt.Errorf("recovery id must be 0-3")
  70  		return
  71  	}
  72  
  73  	sig = make([]byte, RecoverableSignatureSize)
  74  	ret := ecdsaRecoverableSignatureParseCompact(c.ctx, &sig[0], &input64[0], recid)
  75  	if ret != 1 {
  76  		err = fmt.Errorf("failed to parse recoverable signature")
  77  		return
  78  	}
  79  
  80  	return
  81  }
  82  
  83  // Recover recovers a public key from a recoverable signature
  84  func (c *Context) Recover(sig []byte, msg32 []byte) (pubkey []byte, err error) {
  85  	if ecdsaRecover == nil {
  86  		err = fmt.Errorf("recovery module not available")
  87  		return
  88  	}
  89  
  90  	if len(sig) != RecoverableSignatureSize {
  91  		err = fmt.Errorf("recoverable signature must be %d bytes", RecoverableSignatureSize)
  92  		return
  93  	}
  94  
  95  	if len(msg32) != 32 {
  96  		err = fmt.Errorf("message must be 32 bytes")
  97  		return
  98  	}
  99  
 100  	pubkey = make([]byte, PublicKeySize)
 101  	ret := ecdsaRecover(c.ctx, &pubkey[0], &sig[0], &msg32[0])
 102  	if ret != 1 {
 103  		err = fmt.Errorf("failed to recover public key")
 104  		return
 105  	}
 106  
 107  	return
 108  }
 109