github.com/ronperry/cryptoedge@v0.0.0-20150815114006-cc363e290743/jcc/client.go (about)

     1  // Package jcc implements "An ECC-Based Blind Signature Scheme" by Fuh-Gwo Jeng, Tzer-Long Chen and Tzer-Shyong Chen
     2  // A lot of the sanity checks performed by the code make no mathematical sense since they are impossible to produce if the code is actually bug-less
     3  // Under certain conditions both msg and the image of the msg have valid signatures (implausible)
     4  //
     5  // Generate key:
     6  // 		Private key == blinding factor (ni)
     7  // Blind:
     8  // 		blind message = scalarmult(message,scalarmult(blinding factor, PublicKey)) (POINT)
     9  // Sign:
    10  // 		r = nv x blind message (POINT); s = (nv+ns) x blind message (POINT)
    11  // 		ns is the privat key of the signer
    12  //		record nv,blind message. protect priv-key of signer
    13  // Unblind:
    14  // 		s' = s - m x ni x Ps   (Ps public key signer) (POINT)
    15  // 		m' = ni(ni-1)m
    16  // Verify:
    17  //		r == s' - m' x Ps
    18  //
    19  // Public data:
    20  //		Signer: Public Key. Private key and token remain secret
    21  //		Client:
    22  // 			Blind() output: bmsg is public and sent to Signer. bfac is secret, needed for unblinding
    23  //				bfac should be destroyed after unblind (and verification)
    24  // 			Blind() input  msg must be retained until unblinding and destroyed after
    25  // 		Signature (r, sb, mb):
    26  //			From signer -> r
    27  //			From client -> Output of Unblind(): sb, mb
    28  //		Verification operates on: Signer public key, Signature(r, sb, mb)
    29  //
    30  // For more information: http://ojs.academypublisher.com/index.php/jnw/article/viewFile/0508921928/2053
    31  //
    32  package jcc
    33  
    34  import (
    35  	"github.com/ronperry/cryptoedge/eccutil"
    36  	"math/big"
    37  )
    38  
    39  // MaxLoopCount is the maximum number of tries we do for parameter search
    40  const MaxLoopCount = 1000
    41  
    42  // Refactor begin
    43  
    44  // BlindingClient a blinding client
    45  type BlindingClient struct {
    46  	curve  *eccutil.Curve
    47  	PubKey *eccutil.Point
    48  }
    49  
    50  // NewBlindingClient returns a new BlindingClient
    51  func NewBlindingClient(curve *eccutil.Curve, pubKey *eccutil.Point) *BlindingClient {
    52  	bc := new(BlindingClient)
    53  	bc.curve = curve
    54  	bc.PubKey = pubKey
    55  	return bc
    56  }
    57  
    58  // Blind returns a blinded message and the blinding factor. bmsg is sent to signer (public), bfac is private and needed for unblinding
    59  func (client BlindingClient) Blind(msg []byte) (bmsg *eccutil.Point, bfac []byte, err error) {
    60  	// blind message = scalarmult(message,scalarmult(blinding factor, scalarmult(blindingfactor,basepoint)) (POINT)
    61  	var loopcount int
    62  	if len(msg) < 10 {
    63  		return nil, nil, eccutil.ErrMsgShort
    64  	}
    65  	t := new(big.Int)
    66  	t.SetBytes(msg)
    67  	_, err = client.curve.TestCoordinate(t)
    68  	if err != nil {
    69  		return nil, nil, err
    70  	}
    71  	//cparams := client.curve.Params()
    72  	for {
    73  		if loopcount > MaxLoopCount {
    74  			return nil, nil, eccutil.ErrMaxLoop
    75  		}
    76  		loopcount++
    77  		bfact, bpoint, err := client.curve.GenerateKey()
    78  		if err != nil {
    79  			return nil, nil, err
    80  		}
    81  		bfac2 := client.curve.ScalarMult(bpoint, bfact)
    82  		_, err = client.curve.TestPoint(bpoint.X, bpoint.Y, bfac2.X, bfac2.Y) // This cannot really happen
    83  		if err != nil {
    84  			return nil, nil, err
    85  		}
    86  		_, err = client.curve.TestPoint(bfac2.X, bfac2.Y, client.curve.Params.Gx, client.curve.Params.Gy)
    87  		if err != nil {
    88  			continue
    89  		}
    90  		bmsgt := client.curve.ScalarMult(bfac2, msg)
    91  		_, err = client.curve.TestPoint(bpoint.X, bpoint.Y, bmsgt.X, bmsgt.Y)
    92  		if err != nil {
    93  			continue
    94  		}
    95  		_, err = client.curve.TestPoint(bfac2.X, bfac2.Y, bmsgt.X, bmsgt.Y) // This cannot really happen
    96  		if err != nil {
    97  			return nil, nil, err
    98  		}
    99  		_, err = client.curve.TestPoint(bmsgt.X, bmsgt.Y, client.curve.Params.Gx, client.curve.Params.Gy)
   100  		if err != nil {
   101  			continue
   102  		}
   103  		return bmsgt, bfact, nil
   104  	}
   105  }
   106  
   107  // Unblind unblinds a signature. sb and mb are required for verification
   108  func (client BlindingClient) Unblind(bfac, msg []byte, s *eccutil.Point) (sb *eccutil.Point, mb []byte) {
   109  	ni := new(big.Int)
   110  	m := new(big.Int)
   111  	mbt := new(big.Int)
   112  	nim := new(big.Int)
   113  
   114  	// Calculate m' = ni(ni-1)*m
   115  	ni.SetBytes(bfac)
   116  	m.SetBytes(msg)
   117  	nim = nim.Mul(ni, nim.Sub(ni, big.NewInt(1))) // ni(ni-1)
   118  	mbt = mbt.Mul(nim, m)                         // (ni(ni-1))*m
   119  	mbt = eccutil.ManyMult(ni, nim.Sub(ni, big.NewInt(1)), m)
   120  	mbx := mbt.Bytes()
   121  
   122  	// Calculate: s' = s - m x ni x Ps   (Ps public key signer) (POINT)
   123  	nit := client.curve.ScalarMult(client.PubKey, bfac) // ni x Ps
   124  	mt := client.curve.ScalarMult(nit, msg)             // m x (ni x Ps)
   125  	// inverse mt to make substraction
   126  	mt.Y = mt.Y.Neg(mt.Y)
   127  	st := client.curve.AddPoints(s, mt) // s - (m x ni x Ps)
   128  	return st, mbx
   129  }
   130  
   131  // Verify a signature
   132  func (client BlindingClient) Verify(r, sb *eccutil.Point, mb []byte) bool {
   133  	//		r == s' - m' x Ps
   134  	c := client.curve.ScalarMult(client.PubKey, mb) // m' x Ps
   135  	c.Y = c.Y.Neg(c.Y)                              // neg m'
   136  	cv := client.curve.AddPoints(sb, c)             // s + neg (m x Ps)
   137  	if r.X.Cmp(cv.X) == 0 && r.Y.Cmp(cv.Y) == 0 {   // r == s + neg (m x Ps) ?
   138  		return true
   139  	}
   140  	return false
   141  }