2021-11-22 16:05:02 +00:00

178 lines
4.9 KiB
Go

// Copyright 2017-2021 DERO Project. All rights reserved.
// Use of this source code in any form is governed by RESEARCH license.
// license can be found in the LICENSE file.
// GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
//
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package crypto
//import "fmt"
import "math/big"
//import "crypto/rand"
//import "encoding/hex"
import "github.com/deroproject/derohe/cryptography/bn256"
//import "golang.org/x/crypto/sha3"
// a ZERO
var ElGamal_ZERO *bn256.G1
var ElGamal_ZERO_string string
var ElGamal_BASE_G *bn256.G1
type ElGamal struct {
G *bn256.G1
Randomness *big.Int
Left *bn256.G1
Right *bn256.G1
}
func NewElGamal() (p *ElGamal) {
return &ElGamal{G: global_pedersen_values.G}
}
func CommitElGamal(key *bn256.G1, value *big.Int) *ElGamal {
e := NewElGamal()
e.Randomness = RandomScalarFixed()
e.Left = new(bn256.G1).Add(new(bn256.G1).ScalarMult(e.G, value), new(bn256.G1).ScalarMult(key, e.Randomness))
e.Right = new(bn256.G1).ScalarMult(G, e.Randomness)
return e
}
func ConstructElGamal(left, right *bn256.G1) *ElGamal {
e := NewElGamal()
if left != nil {
e.Left = new(bn256.G1).Set(left)
}
e.Right = new(bn256.G1).Set(right)
return e
}
func (e *ElGamal) IsZero() bool {
if e.Left != nil && e.Right != nil && e.Left.String() == ElGamal_ZERO_string && e.Right.String() == ElGamal_ZERO_string {
return true
}
return false
}
func (e *ElGamal) Add(addendum *ElGamal) *ElGamal {
if e.Left == nil {
return ConstructElGamal(nil, new(bn256.G1).Add(e.Right, addendum.Right))
}
return ConstructElGamal(new(bn256.G1).Add(e.Left, addendum.Left), new(bn256.G1).Add(e.Right, addendum.Right))
}
func (e *ElGamal) Mul(scalar *big.Int) *ElGamal {
return ConstructElGamal(new(bn256.G1).ScalarMult(e.Left, scalar), new(bn256.G1).ScalarMult(e.Right, scalar))
}
func (e *ElGamal) Plus(value *big.Int) *ElGamal {
if e.Right == nil {
return ConstructElGamal(new(bn256.G1).Add(e.Left, new(bn256.G1).ScalarMult(e.G, value)), nil)
}
return ConstructElGamal(new(bn256.G1).Add(e.Left, new(bn256.G1).ScalarMult(e.G, value)), new(bn256.G1).Set(e.Right))
}
func (e *ElGamal) Serialize() (data []byte) {
if e.Left == nil || e.Right == nil {
panic("elgamal has nil pointer")
}
data = append(data, e.Left.EncodeCompressed()...)
data = append(data, e.Right.EncodeCompressed()...)
return data
}
func (e *ElGamal) Deserialize(data []byte) *ElGamal {
if len(data) != 66 {
panic("insufficient buffer size")
}
//var left,right *bn256.G1
left := new(bn256.G1)
right := new(bn256.G1)
if err := left.DecodeCompressed(data[:33]); err != nil {
panic(err)
}
if err := right.DecodeCompressed(data[33:66]); err != nil {
panic(err)
}
e = ConstructElGamal(left, right)
return e
}
func (e *ElGamal) Neg() *ElGamal {
var left, right *bn256.G1
if e.Left != nil {
left = new(bn256.G1).Neg(e.Left)
}
if e.Right != nil {
right = new(bn256.G1).Neg(e.Right)
}
return ConstructElGamal(left, right)
}
type ElGamalVector struct {
vector []*ElGamal
}
func (e *ElGamalVector) MultiExponentiate(exponents *FieldVector) *ElGamal {
accumulator := ConstructElGamal(ElGamal_ZERO, ElGamal_ZERO)
for i := range exponents.vector {
accumulator = accumulator.Add(e.vector[i].Mul(exponents.vector[i]))
}
return accumulator
}
func (e *ElGamalVector) Sum() *ElGamal {
r := ConstructElGamal(ElGamal_ZERO, ElGamal_ZERO)
for i := range e.vector {
r = r.Add(e.vector[i])
}
return r
}
func (e *ElGamalVector) Add(other *ElGamalVector) *ElGamalVector {
var r ElGamalVector
for i := range e.vector {
r.vector = append(r.vector, ConstructElGamal(e.vector[i].Left, e.vector[i].Right))
}
for i := range other.vector {
r.vector[i] = r.vector[i].Add(other.vector[i])
}
return &r
}
func (e *ElGamalVector) Hadamard(exponents FieldVector) *ElGamalVector {
var r ElGamalVector
for i := range e.vector {
r.vector = append(r.vector, ConstructElGamal(e.vector[i].Left, e.vector[i].Right))
}
for i := range exponents.vector {
r.vector[i] = r.vector[i].Mul(exponents.vector[i])
}
return &r
}
func (e *ElGamalVector) Times(scalar *big.Int) *ElGamalVector {
var r ElGamalVector
for i := range e.vector {
r.vector = append(r.vector, e.vector[i].Mul(scalar))
}
return &r
}