...
  
  
     1  
     2  
     3  
     4  
     5  
     6  
     7  
     8  
     9  
    10  
    11  
    12  
    13  
    14  
    15  
    16  
    17  
    18  
    19  package elgamal 
    20  
    21  import (
    22  	"crypto/rand"
    23  	"crypto/subtle"
    24  	"errors"
    25  	"io"
    26  	"math/big"
    27  )
    28  
    29  
    30  type PublicKey struct {
    31  	G, P, Y *big.Int
    32  }
    33  
    34  
    35  type PrivateKey struct {
    36  	PublicKey
    37  	X *big.Int
    38  }
    39  
    40  
    41  
    42  
    43  func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
    44  	pLen := (pub.P.BitLen() + 7) / 8
    45  	if len(msg) > pLen-11 {
    46  		err = errors.New("elgamal: message too long")
    47  		return
    48  	}
    49  
    50  	
    51  	em := make([]byte, pLen-1)
    52  	em[0] = 2
    53  	ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
    54  	err = nonZeroRandomBytes(ps, random)
    55  	if err != nil {
    56  		return
    57  	}
    58  	em[len(em)-len(msg)-1] = 0
    59  	copy(mm, msg)
    60  
    61  	m := new(big.Int).SetBytes(em)
    62  
    63  	k, err := rand.Int(random, pub.P)
    64  	if err != nil {
    65  		return
    66  	}
    67  
    68  	c1 = new(big.Int).Exp(pub.G, k, pub.P)
    69  	s := new(big.Int).Exp(pub.Y, k, pub.P)
    70  	c2 = s.Mul(s, m)
    71  	c2.Mod(c2, pub.P)
    72  
    73  	return
    74  }
    75  
    76  
    77  
    78  
    79  
    80  
    81  
    82  
    83  func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
    84  	s := new(big.Int).Exp(c1, priv.X, priv.P)
    85  	if s.ModInverse(s, priv.P) == nil {
    86  		return nil, errors.New("elgamal: invalid private key")
    87  	}
    88  	s.Mul(s, c2)
    89  	s.Mod(s, priv.P)
    90  	em := s.Bytes()
    91  
    92  	firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
    93  
    94  	
    95  	
    96  	
    97  	
    98  	var lookingForIndex, index int
    99  	lookingForIndex = 1
   100  
   101  	for i := 1; i < len(em); i++ {
   102  		equals0 := subtle.ConstantTimeByteEq(em[i], 0)
   103  		index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
   104  		lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
   105  	}
   106  
   107  	if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
   108  		return nil, errors.New("elgamal: decryption error")
   109  	}
   110  	return em[index+1:], nil
   111  }
   112  
   113  
   114  func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
   115  	_, err = io.ReadFull(rand, s)
   116  	if err != nil {
   117  		return
   118  	}
   119  
   120  	for i := 0; i < len(s); i++ {
   121  		for s[i] == 0 {
   122  			_, err = io.ReadFull(rand, s[i:i+1])
   123  			if err != nil {
   124  				return
   125  			}
   126  		}
   127  	}
   128  
   129  	return
   130  }
   131  
View as plain text