mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 05:41:35 +00:00
632 lines
18 KiB
Go
632 lines
18 KiB
Go
package privacy
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
|
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/log"
|
|
)
|
|
|
|
// These constants define the lengths of serialized public keys.
|
|
const (
|
|
PubKeyBytesLenCompressed = 33
|
|
PubKeyBytesLenUncompressed = 65
|
|
PubKeyBytesLenHybrid = 65
|
|
)
|
|
|
|
const (
|
|
pubkeyCompressed byte = 0x2 // y_bit + x coord
|
|
pubkeyUncompressed byte = 0x4 // x coord + y coord
|
|
pubkeyHybrid byte = 0x6 // y_bit + x coord + y coord
|
|
)
|
|
|
|
// The proof contains pretty much stuffs
|
|
// The proof contains pretty much stuffs
|
|
// Ring size rs: 1 byte => proof[0]
|
|
// num input: number of real inputs: 1 byte => proof[1]
|
|
// List of inputs/UTXO index typed uint64 => total size = rs * numInput * 8 = proof[0]*proof[1]*8
|
|
// List of key images: total size = numInput * 33 = proof[1] * 33
|
|
// number of output n: 1 byte
|
|
// List of output => n * 130 bytes
|
|
// transaction fee: uint256 => 32 byte
|
|
// ringCT proof size ctSize: uint16 => 2 byte
|
|
// ringCT proof: ctSize bytes
|
|
// bulletproofs: bp
|
|
type PrivateSendVerifier struct {
|
|
proof []byte
|
|
//ringCT RingCT
|
|
}
|
|
|
|
type Ring []*ecdsa.PublicKey
|
|
|
|
type RingSignature struct {
|
|
NumRing int
|
|
Size int // size of ring
|
|
M [32]byte // message
|
|
C *big.Int // ring signature value, 1 element
|
|
S [][]*big.Int // ring signature values: [NumRing][Size]
|
|
Ring []Ring // array of rings of pubkeys: [NumRing]
|
|
I []*ecdsa.PublicKey // key images, size = the number of rings [NumRing]
|
|
Curve elliptic.Curve
|
|
SerializedRing []byte //temporary memory stored the raw ring ct used in case of verifying ringCT with message verification
|
|
}
|
|
|
|
func (p *PrivateSendVerifier) verify() bool {
|
|
return false
|
|
}
|
|
|
|
func (p *PrivateSendVerifier) deserialize() {
|
|
|
|
}
|
|
|
|
// helper function, returns type of v
|
|
func typeof(v interface{}) string {
|
|
return fmt.Sprintf("%T", v)
|
|
}
|
|
|
|
func isOdd(a *big.Int) bool {
|
|
return a.Bit(0) == 1
|
|
}
|
|
|
|
// SerializeCompressed serializes a public key in a 33-byte compressed format.
|
|
func SerializeCompressed(p *ecdsa.PublicKey) []byte {
|
|
b := make([]byte, 0, PubKeyBytesLenCompressed)
|
|
format := pubkeyCompressed
|
|
if isOdd(p.Y) {
|
|
format |= 0x1
|
|
}
|
|
b = append(b, format)
|
|
return append(b, PadTo32Bytes(p.X.Bytes())...)
|
|
}
|
|
|
|
func DeserializeCompressed(curve elliptic.Curve, b []byte) *ecdsa.PublicKey {
|
|
x := new(big.Int).SetBytes(b[1:33])
|
|
// Y = +-sqrt(x^3 + B)
|
|
x3 := new(big.Int).Mul(x, x)
|
|
x3.Mul(x3, x)
|
|
x3.Add(x3, curve.Params().B)
|
|
|
|
// now calculate sqrt mod p of x2 + B
|
|
// This code used to do a full sqrt based on tonelli/shanks,
|
|
// but this was replaced by the algorithms referenced in
|
|
// https://bitcointalk.org/index.php?topic=162805.msg1712294#msg1712294
|
|
PPlus1Div4 := new(big.Int).Add(curve.Params().P, big.NewInt(1))
|
|
PPlus1Div4 = PPlus1Div4.Div(PPlus1Div4, big.NewInt(4))
|
|
y := new(big.Int).Exp(x3, PPlus1Div4, curve.Params().P)
|
|
ybit := b[0]%2 == 1
|
|
if ybit != isOdd(y) {
|
|
y.Sub(curve.Params().P, y)
|
|
}
|
|
if ybit != isOdd(y) {
|
|
return nil
|
|
}
|
|
return &ecdsa.PublicKey{curve, x, y}
|
|
}
|
|
|
|
// bytes returns the public key ring as a byte slice.
|
|
func (r Ring) Bytes() (b []byte) {
|
|
for _, pub := range r {
|
|
b = append(b, PadTo32Bytes(pub.X.Bytes())...)
|
|
b = append(b, PadTo32Bytes(pub.Y.Bytes())...)
|
|
}
|
|
return
|
|
}
|
|
|
|
func PadTo32Bytes(in []byte) []byte {
|
|
padded := make([]byte, 32)
|
|
if len(in) >= 32 {
|
|
copy(padded, in)
|
|
} else {
|
|
copy(padded[32-len(in):], in)
|
|
}
|
|
|
|
return padded
|
|
}
|
|
|
|
// converts the signature to a byte array
|
|
// this is the format that will be used when passing EVM bytecode
|
|
func (r *RingSignature) Serialize() ([]byte, error) {
|
|
sig := []byte{}
|
|
// add size and message
|
|
b := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(b, uint64(r.NumRing))
|
|
sig = append(sig, b[:]...) // 8 bytes
|
|
|
|
b = make([]byte, 8)
|
|
binary.BigEndian.PutUint64(b, uint64(r.Size))
|
|
sig = append(sig, b[:]...) // 8 bytes
|
|
|
|
sig = append(sig, PadTo32Bytes(r.M[:])...) // 32 bytes
|
|
sig = append(sig, PadTo32Bytes(r.C.Bytes())...) // 32 bytes
|
|
|
|
for k := 0; k < r.NumRing; k++ {
|
|
// 96 bytes each iteration
|
|
for i := 0; i < r.Size; i++ {
|
|
sig = append(sig, PadTo32Bytes(r.S[k][i].Bytes())...)
|
|
}
|
|
}
|
|
for k := 0; k < r.NumRing; k++ {
|
|
// 96 bytes each iteration
|
|
for i := 0; i < r.Size; i++ {
|
|
rb := SerializeCompressed(r.Ring[k][i])
|
|
sig = append(sig, rb...)
|
|
}
|
|
}
|
|
|
|
for k := 0; k < r.NumRing; k++ {
|
|
// 64 bytes
|
|
rb := SerializeCompressed(r.I[k])
|
|
sig = append(sig, rb...)
|
|
}
|
|
|
|
if len(sig) != 8+8+32+32+(32+33)*r.NumRing*r.Size+33*r.NumRing {
|
|
return []byte{}, errors.New("could not serialize ring signature")
|
|
}
|
|
|
|
return sig, nil
|
|
}
|
|
|
|
func computeSignatureSize(numRing int, ringSize int) int {
|
|
const MaxInt = int(^uint(0) >> 1)
|
|
|
|
if numRing < 0 || ringSize < 0 {
|
|
return -1
|
|
}
|
|
|
|
// Calculate term and check for overflow
|
|
|
|
term := numRing * ringSize * 65
|
|
|
|
if term < 0 || term < numRing || term < ringSize {
|
|
return -1
|
|
}
|
|
|
|
return 8 + 8 + 32 + 32 + numRing*ringSize*32 + numRing*ringSize*33 + numRing*33
|
|
}
|
|
|
|
// deserializes the byteified signature into a RingSignature struct
|
|
func Deserialize(r []byte) (*RingSignature, error) {
|
|
if len(r) < 16 {
|
|
return nil, errors.New("failed to deserialize ring signature")
|
|
}
|
|
offset := 0
|
|
sig := new(RingSignature)
|
|
numRing := r[offset : offset+8]
|
|
offset += 8
|
|
size := r[offset : offset+8]
|
|
offset += 8
|
|
|
|
size_uint := binary.BigEndian.Uint64(size)
|
|
size_int := int(size_uint)
|
|
sig.Size = size_int
|
|
|
|
size_uint = binary.BigEndian.Uint64(numRing)
|
|
size_int = int(size_uint)
|
|
sig.NumRing = size_int
|
|
|
|
if len(r) != computeSignatureSize(sig.NumRing, sig.Size) {
|
|
return nil, fmt.Errorf("incorrect ring size, len r: %d, sig.NumRing: %d sig.Size: %d", len(r), sig.NumRing, sig.Size)
|
|
}
|
|
|
|
m := r[offset : offset+32]
|
|
offset += 32
|
|
|
|
var m_byte [32]byte
|
|
copy(m_byte[:], m)
|
|
|
|
sig.M = m_byte
|
|
sig.C = new(big.Int).SetBytes(r[offset : offset+32])
|
|
offset += 32
|
|
|
|
sig.S = make([][]*big.Int, sig.NumRing)
|
|
for i := 0; i < sig.NumRing; i++ {
|
|
sig.S[i] = make([]*big.Int, sig.Size)
|
|
for j := 0; j < sig.Size; j++ {
|
|
sig.S[i][j] = new(big.Int).SetBytes(r[offset : offset+32])
|
|
offset += 32
|
|
}
|
|
}
|
|
|
|
sig.Curve = crypto.S256()
|
|
|
|
sig.Ring = make([]Ring, sig.NumRing)
|
|
for i := 0; i < sig.NumRing; i++ {
|
|
sig.Ring[i] = make([]*ecdsa.PublicKey, sig.Size)
|
|
for j := 0; j < sig.Size; j++ {
|
|
compressedKey := r[offset : offset+33]
|
|
offset += 33
|
|
compressedPubKey := DeserializeCompressed(sig.Curve, compressedKey)
|
|
sig.Ring[i][j] = compressedPubKey
|
|
}
|
|
}
|
|
|
|
sig.I = make([]*ecdsa.PublicKey, sig.NumRing)
|
|
for i := 0; i < sig.NumRing; i++ {
|
|
compressedKey := r[offset : offset+33]
|
|
offset += 33
|
|
compressedPubKey := DeserializeCompressed(sig.Curve, compressedKey)
|
|
sig.I[i] = compressedPubKey
|
|
}
|
|
|
|
sig.SerializedRing = r
|
|
|
|
if !Verify(sig, false) {
|
|
return nil, errors.New("failed to deserialize, invalid ring signature")
|
|
}
|
|
|
|
return sig, nil
|
|
}
|
|
|
|
// takes public key ring and places the public key corresponding to `privkey` in index s of the ring
|
|
// returns a key ring of type []*ecdsa.PublicKey
|
|
func GenKeyRing(ring []*ecdsa.PublicKey, privkey *ecdsa.PrivateKey, s int) ([]*ecdsa.PublicKey, error) {
|
|
size := len(ring) + 1
|
|
new_ring := make([]*ecdsa.PublicKey, size)
|
|
pubkey := privkey.Public().(*ecdsa.PublicKey)
|
|
|
|
if s > len(ring) {
|
|
return nil, errors.New("index s out of bounds")
|
|
}
|
|
|
|
new_ring[s] = pubkey
|
|
for i := 1; i < size; i++ {
|
|
idx := (i + s) % size
|
|
new_ring[idx] = ring[i-1]
|
|
}
|
|
|
|
return new_ring, nil
|
|
}
|
|
|
|
// creates a ring with size specified by `size` and places the public key corresponding to `privkey` in index s of the ring
|
|
// returns a new key ring of type []*ecdsa.PublicKey
|
|
func GenNewKeyRing(size int, privkey *ecdsa.PrivateKey, s int) ([]*ecdsa.PublicKey, error) {
|
|
ring := make([]*ecdsa.PublicKey, size)
|
|
pubkey := privkey.Public().(*ecdsa.PublicKey)
|
|
|
|
if s >= len(ring) {
|
|
return nil, errors.New("index s out of bounds")
|
|
}
|
|
|
|
ring[s] = pubkey
|
|
|
|
for i := 1; i < size; i++ {
|
|
idx := (i + s) % size
|
|
priv, err := crypto.GenerateKey()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
pub := priv.Public()
|
|
ring[idx] = pub.(*ecdsa.PublicKey)
|
|
}
|
|
|
|
return ring, nil
|
|
}
|
|
|
|
// calculate key image I = x * H_p(P) where H_p is a hash function that returns a point
|
|
// H_p(P) = sha3(P) * G
|
|
func GenKeyImage(privkey *ecdsa.PrivateKey) *ecdsa.PublicKey {
|
|
pubkey := privkey.Public().(*ecdsa.PublicKey)
|
|
image := new(ecdsa.PublicKey)
|
|
|
|
// calculate sha3(P)
|
|
h_x, h_y := HashPoint(pubkey)
|
|
|
|
// calculate H_p(P) = x * sha3(P) * G
|
|
i_x, i_y := privkey.Curve.ScalarMult(h_x, h_y, privkey.D.Bytes())
|
|
|
|
image.X = i_x
|
|
image.Y = i_y
|
|
return image
|
|
}
|
|
|
|
func HashPoint(p *ecdsa.PublicKey) (*big.Int, *big.Int) {
|
|
input := append(PadTo32Bytes(p.X.Bytes()), PadTo32Bytes(p.Y.Bytes())...)
|
|
log.Info("HashPoint", "input ", common.Bytes2Hex(input))
|
|
hash := crypto.Keccak256(input)
|
|
log.Info("HashPoint", "hash ", common.Bytes2Hex(hash))
|
|
return p.Curve.ScalarBaseMult(hash[:])
|
|
}
|
|
|
|
// create ring signature from list of public keys given inputs:
|
|
// msg: byte array, message to be signed
|
|
// ring: array of *ecdsa.PublicKeys to be included in the ring
|
|
// privkey: *ecdsa.PrivateKey of signer
|
|
// s: index of signer in ring
|
|
func Sign(m [32]byte, rings []Ring, privkeys []*ecdsa.PrivateKey, s int) (*RingSignature, error) {
|
|
numRing := len(rings)
|
|
if numRing < 1 {
|
|
return nil, errors.New("there is no ring to make signature")
|
|
}
|
|
// check ringsize > 1
|
|
ringsize := len(rings[0])
|
|
if ringsize < 2 {
|
|
return nil, errors.New("size of ring less than two")
|
|
} else if s >= ringsize || s < 0 {
|
|
return nil, errors.New("secret index out of range of ring size")
|
|
}
|
|
|
|
// setup
|
|
//pubkey := privkey.Public().(*ecdsa.PublicKey)
|
|
pubkeys := make([]*ecdsa.PublicKey, numRing)
|
|
for i := 0; i < numRing; i++ {
|
|
pubkeys[i] = &privkeys[i].PublicKey
|
|
}
|
|
//cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated
|
|
curve := pubkeys[0].Curve.(*secp256k1.BitCurve)
|
|
sig := new(RingSignature)
|
|
sig.Size = ringsize
|
|
sig.NumRing = numRing
|
|
sig.M = m
|
|
sig.Ring = rings
|
|
sig.Curve = curve
|
|
|
|
// check that key at index s is indeed the signer
|
|
for i := 0; i < numRing; i++ {
|
|
if rings[i][s] != pubkeys[i] {
|
|
return nil, errors.New("secret index in ring is not signer")
|
|
}
|
|
}
|
|
|
|
// generate key image
|
|
images := make([]*ecdsa.PublicKey, numRing)
|
|
for i := 0; i < numRing; i++ {
|
|
images[i] = GenKeyImage(privkeys[i])
|
|
}
|
|
sig.I = images
|
|
|
|
// start at c[1]
|
|
// pick random scalar u (glue value), calculate c[1] = H(m, u*G) where H is a hash function and G is the base point of the curve
|
|
C := make([]*big.Int, ringsize)
|
|
S := make([][]*big.Int, numRing)
|
|
for i := 0; i < numRing; i++ {
|
|
S[i] = make([]*big.Int, ringsize)
|
|
}
|
|
|
|
//Initialize S except S[..][s]
|
|
for i := 0; i < numRing; i++ {
|
|
for j := 0; j < ringsize; j++ {
|
|
if j != s {
|
|
randomGenerated, err := rand.Int(rand.Reader, curve.Params().P)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
S[i][j] = randomGenerated
|
|
}
|
|
}
|
|
}
|
|
|
|
L := make([][]*ecdsa.PublicKey, numRing)
|
|
R := make([][]*ecdsa.PublicKey, numRing)
|
|
for i := 0; i < numRing; i++ {
|
|
L[i] = make([]*ecdsa.PublicKey, ringsize)
|
|
R[i] = make([]*ecdsa.PublicKey, ringsize)
|
|
}
|
|
alpha := make([]*big.Int, numRing)
|
|
|
|
var l []byte
|
|
//compute L[i][s], R[i][s], i = 0..numRing
|
|
for i := 0; i < numRing; i++ {
|
|
randomGenerated, err := rand.Int(rand.Reader, curve.Params().P)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
alpha[i] = randomGenerated
|
|
// start at secret index s/PI
|
|
// compute L_s = u*G
|
|
l_x, l_y := curve.ScalarBaseMult(PadTo32Bytes(alpha[i].Bytes()))
|
|
L[i][s] = &ecdsa.PublicKey{curve, l_x, l_y}
|
|
lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...)
|
|
l = append(l, lT...)
|
|
// compute R_s = u*H_p(P[s])
|
|
h_x, h_y := HashPoint(pubkeys[i])
|
|
r_x, r_y := curve.ScalarMult(h_x, h_y, PadTo32Bytes(alpha[i].Bytes()))
|
|
R[i][s] = &ecdsa.PublicKey{curve, r_x, r_y}
|
|
rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...)
|
|
l = append(l, rT...)
|
|
}
|
|
|
|
// concatenate m and u*G and calculate c[s+1] = H(m, L_s, R_s)
|
|
C_j := crypto.Keccak256(append(m[:], l...))
|
|
idx := s + 1
|
|
if idx == ringsize {
|
|
idx = 0
|
|
}
|
|
if idx == 0 {
|
|
C[0] = new(big.Int).SetBytes(C_j[:])
|
|
} else {
|
|
C[idx] = new(big.Int).SetBytes(C_j[:])
|
|
}
|
|
for idx != s {
|
|
var l []byte
|
|
for j := 0; j < numRing; j++ {
|
|
// calculate L[j][idx] = s[j][idx]*G + c[idx]*Ring[j][idx]
|
|
px, py := curve.ScalarMult(rings[j][idx].X, rings[j][idx].Y, PadTo32Bytes(C[idx].Bytes())) // px, py = c_i*P_i
|
|
sx, sy := curve.ScalarBaseMult(PadTo32Bytes(S[j][idx].Bytes())) // sx, sy = s[n-1]*G
|
|
if px == nil || py == nil || sx == nil || sy == nil {
|
|
return nil, errors.New("could not create ring signature")
|
|
}
|
|
l_x, l_y := curve.Add(sx, sy, px, py)
|
|
L[j][idx] = &ecdsa.PublicKey{curve, l_x, l_y}
|
|
lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...)
|
|
l = append(l, lT...)
|
|
|
|
// calculate R[j][idx] = s[j][idx]*H_p(Ring[j][idx]) + c[idx]*I[j]
|
|
px, py = curve.ScalarMult(images[j].X, images[j].Y, C[idx].Bytes()) // px, py = c_i*I
|
|
hx, hy := HashPoint(rings[j][idx])
|
|
sx, sy = curve.ScalarMult(hx, hy, S[j][idx].Bytes()) // sx, sy = s[n-1]*H_p(P_i)
|
|
if px == nil || py == nil || sx == nil || sy == nil {
|
|
return nil, errors.New("could not create ring signature")
|
|
}
|
|
r_x, r_y := curve.Add(sx, sy, px, py)
|
|
R[j][idx] = &ecdsa.PublicKey{curve, r_x, r_y}
|
|
rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...)
|
|
l = append(l, rT...)
|
|
}
|
|
|
|
idx++
|
|
if idx == ringsize {
|
|
idx = 0
|
|
}
|
|
|
|
var ciIdx int
|
|
if idx == 0 {
|
|
ciIdx = 0
|
|
} else {
|
|
ciIdx = idx
|
|
}
|
|
cSha := crypto.Keccak256(append(PadTo32Bytes(m[:]), l...))
|
|
C[ciIdx] = new(big.Int).SetBytes(cSha[:])
|
|
}
|
|
|
|
//compute S[j][s] = alpha[j] - c[s] * privkeys[j], privkeys[j] = private key corresponding to key image I[j]
|
|
for j := 0; j < numRing; j++ {
|
|
cx := C[s]
|
|
// close ring by finding S[j][s] = (alpha[j] - c[s]*privkeys[s] ) mod P where k[s] is the private key and P is the order of the curve
|
|
S[j][s] = new(big.Int).Mod(new(big.Int).Sub(alpha[j], new(big.Int).Mul(cx, privkeys[j].D)), curve.Params().N)
|
|
}
|
|
|
|
// everything ok, add values to signature
|
|
sig.S = S
|
|
sig.C = C[0]
|
|
sig.NumRing = numRing
|
|
sig.Size = ringsize
|
|
sig.C = C[0]
|
|
|
|
return sig, nil
|
|
}
|
|
|
|
// verify ring signature contained in RingSignature struct
|
|
// returns true if a valid signature, false otherwise
|
|
func Verify(sig *RingSignature, verifyMes bool) bool {
|
|
// setup
|
|
rings := sig.Ring
|
|
ringsize := sig.Size
|
|
numRing := sig.NumRing
|
|
S := sig.S
|
|
C := make([]*big.Int, ringsize+1)
|
|
C[0] = sig.C
|
|
//cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated
|
|
curve := sig.Curve.(*secp256k1.BitCurve)
|
|
image := sig.I
|
|
|
|
//check on curve
|
|
for i := 0; i < numRing; i++ {
|
|
onCurve := curve.IsOnCurve(image[i].X, image[i].Y)
|
|
if !onCurve {
|
|
return false
|
|
}
|
|
for j := 0; j < ringsize; j++ {
|
|
onCurve := curve.IsOnCurve(rings[i][j].X, rings[i][j].Y)
|
|
if !onCurve {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
// calculate c[i+1] = H(m, s[i]*G + c[i]*P[i])
|
|
// and c[0] = H)(m, s[n-1]*G + c[n-1]*P[n-1]) where n is the ring size
|
|
//log.Info("C", "0", common.Bytes2Hex(C[0].Bytes()))
|
|
for j := 0; j < ringsize; j++ {
|
|
var l []byte
|
|
for i := 0; i < numRing; i++ {
|
|
// Validate S[i][j] and C[j]
|
|
if !isValidScalar(S[i][j], curve) || !isValidScalar(C[j], curve) {
|
|
return false // Or handle the error as required
|
|
}
|
|
|
|
// calculate L[i][j] = s[i][j]*G + c[j]*Ring[i][j]
|
|
px, py := curve.ScalarMult(rings[i][j].X, rings[i][j].Y, C[j].Bytes()) // px, py = c_i*P_i
|
|
sx, sy := curve.ScalarBaseMult(S[i][j].Bytes()) // sx, sy = s[i]*G
|
|
if px == nil || py == nil || sx == nil || sy == nil {
|
|
return false
|
|
}
|
|
l_x, l_y := curve.Add(sx, sy, px, py)
|
|
lT := append(PadTo32Bytes(l_x.Bytes()), PadTo32Bytes(l_y.Bytes())...)
|
|
//log.Info("L[i][j]", "i", i, "j", j, "L", common.Bytes2Hex(lT))
|
|
l = append(l, lT...)
|
|
|
|
// calculate R_i = s[i][j]*H_p(Ring[i][j]) + c[j]*I[j]
|
|
px, py = curve.ScalarMult(image[i].X, image[i].Y, C[j].Bytes()) // px, py = c[i]*I
|
|
hx, hy := HashPoint(rings[i][j])
|
|
|
|
// Validate S[i][j], hx, and hy
|
|
if !isValidScalar(S[i][j], curve) || !isValidScalar(hx, curve) || !isValidScalar(hy, curve) {
|
|
return false // Or handle the error as required
|
|
}
|
|
//log.Info("H[i][j]", "i", i, "j", j, "x.input", common.Bytes2Hex(rings[i][j].X.Bytes()), "y.input", common.Bytes2Hex(rings[i][j].Y.Bytes()))
|
|
//log.Info("H[i][j]", "i", i, "j", j, "x", common.Bytes2Hex(hx.Bytes()), "y", common.Bytes2Hex(hy.Bytes()))
|
|
sx, sy = curve.ScalarMult(hx, hy, S[i][j].Bytes()) // sx, sy = s[i]*H_p(P[i])
|
|
if px == nil || py == nil || sx == nil || sy == nil {
|
|
return false
|
|
}
|
|
r_x, r_y := curve.Add(sx, sy, px, py)
|
|
rT := append(PadTo32Bytes(r_x.Bytes()), PadTo32Bytes(r_y.Bytes())...)
|
|
//log.Info("R[i][j]", "i", i, "j", j, "L", common.Bytes2Hex(rT))
|
|
l = append(l, rT...)
|
|
}
|
|
|
|
// calculate c[i+1] = H(m, L_i, R_i)
|
|
//cj_mes := append(PadTo32Bytes(sig.M[:]), l...)
|
|
C_j := crypto.Keccak256(append(PadTo32Bytes(sig.M[:]), l...))
|
|
//log.Info("C hash input", "j", j + 1, "C_input", common.Bytes2Hex(cj_mes))
|
|
|
|
/*if j == ringsize-1 {
|
|
C[0] = new(big.Int).SetBytes(C_j[:])
|
|
} else {*/
|
|
C[j+1] = new(big.Int).SetBytes(C_j[:])
|
|
//log.Info("C", "j", j + 1, "C", common.Bytes2Hex(C[j + 1].Bytes()))
|
|
//}
|
|
}
|
|
|
|
return bytes.Equal(sig.C.Bytes(), C[ringsize].Bytes())
|
|
}
|
|
|
|
func isValidScalar(scalar *big.Int, curve elliptic.Curve) bool {
|
|
return scalar.Sign() >= 0 && scalar.Cmp(curve.Params().N) < 0
|
|
}
|
|
|
|
func Link(sig_a *RingSignature, sig_b *RingSignature) bool {
|
|
for i := 0; i < len(sig_a.I); i++ {
|
|
for j := 0; j < len(sig_b.I); j++ {
|
|
if sig_a.I[i].X == sig_b.I[j].X && sig_a.I[i].Y == sig_b.I[j].Y {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// function returns(mutiple rings, private keys, message, error)
|
|
func GenerateMultiRingParams(numRing int, ringSize int, s int) (rings []Ring, privkeys []*ecdsa.PrivateKey, m [32]byte, err error) {
|
|
for i := 0; i < numRing; i++ {
|
|
privkey, err := crypto.GenerateKey()
|
|
if err != nil {
|
|
return nil, nil, [32]byte{}, err
|
|
}
|
|
privkeys = append(privkeys, privkey)
|
|
|
|
ring, err := GenNewKeyRing(ringSize, privkey, s)
|
|
if err != nil {
|
|
return nil, nil, [32]byte{}, err
|
|
}
|
|
rings = append(rings, ring)
|
|
}
|
|
|
|
_, err = rand.Read(m[:])
|
|
if err != nil {
|
|
return nil, nil, [32]byte{}, err
|
|
}
|
|
return rings, privkeys, m, nil
|
|
}
|