package ringct
|
|
|
|
|
|
import "io"
|
|
import "crypto/rand"
|
|
|
|
import "github.com/deroproject/derosuite/crypto"
|
|
|
|
|
|
|
|
const KeyLength = 32
|
|
|
|
|
|
// Key can be a Scalar or a Point
|
|
type Key [KeyLength]byte
|
|
|
|
func (p *Key) FromBytes(b [KeyLength]byte) {
|
|
*p = b
|
|
}
|
|
|
|
func (p *Key) ToBytes() (result [KeyLength]byte) {
|
|
result = [KeyLength]byte(*p)
|
|
return
|
|
}
|
|
|
|
func (p *Key) PubKey() (pubKey *Key) {
|
|
point := new(ExtendedGroupElement)
|
|
GeScalarMultBase(point, p)
|
|
pubKey = new(Key)
|
|
point.ToBytes(pubKey)
|
|
return
|
|
}
|
|
|
|
// Creates a point on the Edwards Curve by hashing the key
|
|
func (p *Key) HashToEC() (result *ExtendedGroupElement) {
|
|
result = new(ExtendedGroupElement)
|
|
var p1 ProjectiveGroupElement
|
|
var p2 CompletedGroupElement
|
|
h := Key(crypto.Keccak256(p[:]))
|
|
p1.FromBytes(&h)
|
|
GeMul8(&p2, &p1)
|
|
p2.ToExtended(result)
|
|
return
|
|
}
|
|
|
|
func RandomScalar() (result *Key) {
|
|
result = new(Key)
|
|
var reduceFrom [KeyLength * 2]byte
|
|
tmp := make([]byte, KeyLength*2)
|
|
rand.Read(tmp)
|
|
copy(reduceFrom[:], tmp)
|
|
ScReduce(result, &reduceFrom)
|
|
return
|
|
}
|
|
|
|
func NewKeyPair() (privKey *Key, pubKey *Key) {
|
|
privKey = RandomScalar()
|
|
pubKey = privKey.PubKey()
|
|
return
|
|
}
|
|
|
|
func ParseKey(buf io.Reader) (result Key, err error) {
|
|
key := make([]byte, KeyLength)
|
|
if _, err = buf.Read(key); err != nil {
|
|
return
|
|
}
|
|
copy(result[:], key)
|
|
return
|
|
}
|
|
|
|
/*
|
|
//does a * G where a is a scalar and G is the curve basepoint
|
|
key scalarmultBase(const key & a) {
|
|
ge_p3 point;
|
|
key aG;
|
|
sc_reduce32copy(aG.bytes, a.bytes); //do this beforehand
|
|
ge_scalarmult_base(&point, aG.bytes);
|
|
ge_p3_tobytes(aG.bytes, &point);
|
|
return aG;
|
|
}
|
|
*/
|
|
//does a * G where a is a scalar and G is the curve basepoint
|
|
|
|
func ScalarmultBase(a Key) (aG Key){
|
|
reduce32copy := a
|
|
ScReduce32(&reduce32copy)
|
|
point := new(ExtendedGroupElement)
|
|
GeScalarMultBase(point, &a)
|
|
point.ToBytes(&aG)
|
|
return aG
|
|
}
|
|
|
|
// generates a key which can be used as private key or mask
|
|
// this function is similiar to RandomScalar except for reduce32, TODO can we merge both
|
|
func skGen() Key {
|
|
skey := RandomScalar()
|
|
ScReduce32(skey)
|
|
return *skey
|
|
}
|
|
|
|
|
|
func (k *Key) ToExtended() (result *ExtendedGroupElement) {
|
|
result = new(ExtendedGroupElement)
|
|
result.FromBytes(k)
|
|
return
|
|
}
|
|
|
|
func identity() (result *Key) {
|
|
result = new(Key)
|
|
result[0] = 1
|
|
return
|
|
}
|
|
|
|
// convert a uint64 to a scalar
|
|
func d2h(val uint64) (result *Key) {
|
|
result = new(Key)
|
|
for i := 0; val > 0; i++ {
|
|
result[i] = byte(val & 0xFF)
|
|
val /= 256
|
|
}
|
|
return
|
|
}
|
|
|
|
func HashToScalar(data ...[]byte) (result *Key) {
|
|
result = new(Key)
|
|
*result = Key(crypto.Keccak256(data...))
|
|
ScReduce32(result)
|
|
return
|
|
}
|
|
|
|
// multiply a scalar by H (second curve point of Pedersen Commitment)
|
|
func ScalarMultH(scalar *Key) (result *Key) {
|
|
h := new(ExtendedGroupElement)
|
|
h.FromBytes(&H)
|
|
resultPoint := new(ProjectiveGroupElement)
|
|
GeScalarMult(resultPoint, scalar, h)
|
|
result = new(Key)
|
|
resultPoint.ToBytes(result)
|
|
return
|
|
}
|
|
|
|
// add two points together
|
|
func AddKeys(sum, k1, k2 *Key) {
|
|
a := k1.ToExtended()
|
|
b := new(CachedGroupElement)
|
|
k2.ToExtended().ToCached(b)
|
|
c := new(CompletedGroupElement)
|
|
geAdd(c, a, b)
|
|
tmp := new(ExtendedGroupElement)
|
|
c.ToExtended(tmp)
|
|
tmp.ToBytes(sum)
|
|
return
|
|
}
|
|
|
|
// compute a*G + b*B
|
|
func AddKeys2(result, a, b, B *Key) {
|
|
BPoint := B.ToExtended()
|
|
RPoint := new(ProjectiveGroupElement)
|
|
GeDoubleScalarMultVartime(RPoint, b, BPoint, a)
|
|
RPoint.ToBytes(result)
|
|
return
|
|
}
|
|
|
|
// subtract two points A - B
|
|
func SubKeys(diff, k1, k2 *Key) {
|
|
a := k1.ToExtended()
|
|
b := new(CachedGroupElement)
|
|
k2.ToExtended().ToCached(b)
|
|
c := new(CompletedGroupElement)
|
|
geSub(c, a, b)
|
|
tmp := new(ExtendedGroupElement)
|
|
c.ToExtended(tmp)
|
|
tmp.ToBytes(diff)
|
|
return
|
|
}
|