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

     1  package privacy
     2  
     3  // elGamalPublicKeyOld represents to public key in ElGamal encryption
     4  // H = G^X, X is private key
     5  type elGamalPublicKey struct {
     6  	h *Point
     7  }
     8  
     9  // elGamalPrivateKeyOld represents to private key in ElGamal encryption
    10  type elGamalPrivateKey struct {
    11  	x *Scalar
    12  }
    13  
    14  // elGamalCipherTextOld represents to ciphertext in ElGamal encryption
    15  // in which C1 = G^k and C2 = H^k * message
    16  // k is a random number (32 bytes), message is an elliptic point
    17  type elGamalCipherText struct {
    18  	c1, c2 *Point
    19  }
    20  
    21  func (ciphertext *elGamalCipherText) set(c1, c2 *Point) {
    22  	ciphertext.c1 = c1
    23  	ciphertext.c2 = c2
    24  }
    25  
    26  func (pub *elGamalPublicKey) set(H *Point) {
    27  	pub.h = H
    28  }
    29  
    30  func (pub elGamalPublicKey) GetH() *Point {
    31  	return pub.h
    32  }
    33  
    34  func (priv *elGamalPrivateKey) set(x *Scalar) {
    35  	priv.x = x
    36  }
    37  
    38  func (priv elGamalPrivateKey) GetX() *Scalar {
    39  	return priv.x
    40  }
    41  
    42  // Bytes converts ciphertext to 66-byte array
    43  func (ciphertext elGamalCipherText) Bytes() []byte {
    44  	if ciphertext.c1.IsIdentity() {
    45  		return []byte{}
    46  	}
    47  	b1 := ciphertext.c1.ToBytes()
    48  	b2 := ciphertext.c2.ToBytes()
    49  	res := append(b1[:], b2[:]...)
    50  	return res
    51  }
    52  
    53  // SetBytes reverts 66-byte array to ciphertext
    54  func (ciphertext *elGamalCipherText) SetBytes(bytes []byte) error {
    55  	if len(bytes) == 0 {
    56  		return NewPrivacyErr(InvalidInputToSetBytesErr, nil)
    57  	}
    58  
    59  	if ciphertext == nil {
    60  		ciphertext = new(elGamalCipherText)
    61  	}
    62  
    63  	var err error
    64  
    65  	var tmp [Ed25519KeySize]byte
    66  	copy(tmp[:], bytes[:Ed25519KeySize])
    67  	ciphertext.c1, err = new(Point).FromBytes(tmp)
    68  	if err != nil {
    69  		return err
    70  	}
    71  	copy(tmp[:], bytes[Ed25519KeySize:])
    72  	ciphertext.c2, err = new(Point).FromBytes(tmp)
    73  	if err != nil {
    74  		return err
    75  	}
    76  
    77  	return nil
    78  }
    79  
    80  // encrypt encrypts plaintext (is an elliptic point) using public key ElGamal
    81  // returns ElGamal ciphertext
    82  func (pub elGamalPublicKey) encrypt(plaintext *Point) *elGamalCipherText {
    83  	// r random, S:= h^r where h = g^x
    84  	r := RandomScalar()
    85  	S := new(Point).ScalarMult(pub.h, r)
    86  
    87  	//return ciphertext (c1, c2) = (g^r, m.s=m.h^r)
    88  	ciphertext := new(elGamalCipherText)
    89  	ciphertext.c1 = new(Point).ScalarMultBase(r)
    90  	ciphertext.c2 = new(Point).Add(plaintext, S)
    91  
    92  	return ciphertext
    93  }
    94  
    95  // decrypt receives a ciphertext and
    96  // decrypts it using private key ElGamal
    97  // and returns plain text in elliptic point
    98  func (priv elGamalPrivateKey) decrypt(ciphertext *elGamalCipherText) (*Point, error) {
    99  	S := new(Point).ScalarMult(ciphertext.c1, priv.x)
   100  	plaintext := new(Point).Sub(ciphertext.c2, S)
   101  	return plaintext, nil
   102  }