github.com/incognitochain/go-incognito-sdk@v1.0.1/privacy/schnorr.go (about)

     1  package privacy
     2  
     3  import (
     4  	"crypto/subtle"
     5  	"errors"
     6  	"github.com/incognitochain/go-incognito-sdk/common"
     7  )
     8  
     9  // SchnorrPublicKey represents Schnorr Publickey
    10  // PK = G^SK + H^R
    11  type SchnorrPublicKey struct {
    12  	publicKey *Point
    13  	g, h      *Point
    14  }
    15  
    16  func (schnorrPubKey SchnorrPublicKey) GetPublicKey() *Point {
    17  	return schnorrPubKey.publicKey
    18  }
    19  
    20  // SchnorrPrivateKey represents Schnorr Privatekey
    21  type SchnorrPrivateKey struct {
    22  	privateKey *Scalar
    23  	randomness *Scalar
    24  	publicKey  *SchnorrPublicKey
    25  }
    26  
    27  func (schnPrivKey SchnorrPrivateKey) GetPublicKey() *SchnorrPublicKey {
    28  	return schnPrivKey.publicKey
    29  }
    30  
    31  // SchnSignature represents Schnorr Signature
    32  type SchnSignature struct {
    33  	e, z1, z2 *Scalar
    34  }
    35  
    36  // Set sets Schnorr private key
    37  func (privateKey *SchnorrPrivateKey) Set(sk *Scalar, r *Scalar) {
    38  	privateKey.privateKey = sk
    39  	privateKey.randomness = r
    40  	privateKey.publicKey = new(SchnorrPublicKey)
    41  	privateKey.publicKey.g, _ = new(Point).SetKey(&PedCom.G[PedersenPrivateKeyIndex].key)
    42  	privateKey.publicKey.h, _ = new(Point).SetKey(&PedCom.G[PedersenRandomnessIndex].key)
    43  	privateKey.publicKey.publicKey = new(Point).ScalarMult(PedCom.G[PedersenPrivateKeyIndex], sk)
    44  	privateKey.publicKey.publicKey.Add(privateKey.publicKey.publicKey, new(Point).ScalarMult(PedCom.G[PedersenRandomnessIndex], r))
    45  }
    46  
    47  // Set sets Schnorr public key
    48  func (publicKey *SchnorrPublicKey) Set(pk *Point) {
    49  	publicKey.publicKey, _ = new(Point).SetKey(&pk.key)
    50  
    51  	publicKey.g, _ = new(Point).SetKey(&PedCom.G[PedersenPrivateKeyIndex].key)
    52  	publicKey.h, _ = new(Point).SetKey(&PedCom.G[PedersenRandomnessIndex].key)
    53  }
    54  
    55  //Sign is function which using for signing on hash array by private key
    56  func (privateKey SchnorrPrivateKey) Sign(data []byte) (*SchnSignature, error) {
    57  	if len(data) != common.HashSize {
    58  		return nil, NewPrivacyErr(UnexpectedErr, errors.New("hash length must be 32 bytes"))
    59  	}
    60  
    61  	signature := new(SchnSignature)
    62  
    63  	// has privacy
    64  	if !privateKey.randomness.IsZero() {
    65  		// generates random numbers s1, s2 in [0, Curve.Params().N - 1]
    66  
    67  		s1 := RandomScalar()
    68  		s2 := RandomScalar()
    69  
    70  		// t = s1*G + s2*H
    71  		t := new(Point).ScalarMult(privateKey.publicKey.g, s1)
    72  		t.Add(t, new(Point).ScalarMult(privateKey.publicKey.h, s2))
    73  
    74  		// E is the hash of elliptic point t and data need to be signed
    75  		msg := append(t.ToBytesS(), data...)
    76  
    77  		signature.e = HashToScalar(msg)
    78  
    79  		signature.z1 = new(Scalar).Mul(privateKey.privateKey, signature.e)
    80  		signature.z1 = new(Scalar).Sub(s1, signature.z1)
    81  
    82  		signature.z2 = new(Scalar).Mul(privateKey.randomness, signature.e)
    83  		signature.z2 = new(Scalar).Sub(s2, signature.z2)
    84  
    85  		return signature, nil
    86  	}
    87  
    88  	// generates random numbers s, k2 in [0, Curve.Params().N - 1]
    89  	s := RandomScalar()
    90  
    91  	// t = s*G
    92  	t := new(Point).ScalarMult(privateKey.publicKey.g, s)
    93  
    94  	// E is the hash of elliptic point t and data need to be signed
    95  	msg := append(t.ToBytesS(), data...)
    96  	signature.e = HashToScalar(msg)
    97  
    98  	// Z1 = s - e*sk
    99  	signature.z1 = new(Scalar).Mul(privateKey.privateKey, signature.e)
   100  	signature.z1 = new(Scalar).Sub(s, signature.z1)
   101  
   102  	signature.z2 = nil
   103  
   104  	return signature, nil
   105  }
   106  
   107  //Verify is function which using for verify that the given signature was signed by by privatekey of the public key
   108  func (publicKey SchnorrPublicKey) Verify(signature *SchnSignature, data []byte) bool {
   109  	if signature == nil {
   110  		return false
   111  	}
   112  	rv := new(Point).ScalarMult(publicKey.publicKey, signature.e)
   113  	rv.Add(rv, new(Point).ScalarMult(publicKey.g, signature.z1))
   114  	if signature.z2 != nil {
   115  		rv.Add(rv, new(Point).ScalarMult(publicKey.h, signature.z2))
   116  	}
   117  	msg := append(rv.ToBytesS(), data...)
   118  
   119  	ev := HashToScalar(msg)
   120  	return subtle.ConstantTimeCompare(ev.ToBytesS(), signature.e.ToBytesS()) == 1
   121  }
   122  
   123  func (sig SchnSignature) Bytes() []byte {
   124  	bytes := append(sig.e.ToBytesS(), sig.z1.ToBytesS()...)
   125  	// Z2 is nil when has no privacy
   126  	if sig.z2 != nil {
   127  		bytes = append(bytes, sig.z2.ToBytesS()...)
   128  	}
   129  	return bytes
   130  }
   131  
   132  func (sig *SchnSignature) SetBytes(bytes []byte) error {
   133  	if len(bytes) == 0 {
   134  		return NewPrivacyErr(InvalidInputToSetBytesErr, nil)
   135  	}
   136  	sig.e = new(Scalar).FromBytesS(bytes[0:Ed25519KeySize])
   137  	sig.z1 = new(Scalar).FromBytesS(bytes[Ed25519KeySize : 2*Ed25519KeySize])
   138  	if len(bytes) == 3*Ed25519KeySize {
   139  		sig.z2 = new(Scalar).FromBytesS(bytes[2*Ed25519KeySize:])
   140  	} else {
   141  		sig.z2 = nil
   142  	}
   143  
   144  	return nil
   145  }