mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
* v2.1.0 [omit consensus and adjacent] - this commit will be amended with the full release after the file copy is complete * 2.1.0 main node rollup
306 lines
7.8 KiB
Go
306 lines
7.8 KiB
Go
package verenc
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"slices"
|
|
"sync"
|
|
|
|
lru "github.com/hashicorp/golang-lru/v2"
|
|
"source.quilibrium.com/quilibrium/monorepo/types/crypto"
|
|
generated "source.quilibrium.com/quilibrium/monorepo/verenc/generated/verenc"
|
|
)
|
|
|
|
var _ crypto.VerifiableEncryptor = (*MPCitHVerifiableEncryptor)(nil)
|
|
|
|
type MPCitHVerEncProof struct {
|
|
generated.VerencProofAndBlindingKey
|
|
}
|
|
|
|
type MPCitHVerEnc struct {
|
|
generated.CompressedCiphertext
|
|
BlindingPubkey []uint8
|
|
Statement []uint8
|
|
}
|
|
|
|
func MPCitHVerEncProofFromBytes(data []byte) MPCitHVerEncProof {
|
|
if len(data) != 9268 {
|
|
return MPCitHVerEncProof{}
|
|
}
|
|
|
|
polycom := [][]byte{}
|
|
for i := 0; i < 23; i++ {
|
|
polycom = append(polycom, data[235+(i*57):292+(i*57)])
|
|
}
|
|
|
|
ctexts := []generated.VerencCiphertext{}
|
|
srs := []generated.VerencShare{}
|
|
|
|
for i := 0; i < 42; i++ {
|
|
ctexts = append(ctexts, generated.VerencCiphertext{
|
|
C1: data[1546+(i*(57+56+8)) : 1603+(i*(57+56+8))],
|
|
C2: data[1603+(i*(57+56+8)) : 1659+(i*(57+56+8))],
|
|
I: binary.BigEndian.Uint64(data[1659+(i*(57+56+8)) : 1667+(i*(57+56+8))]),
|
|
})
|
|
}
|
|
|
|
for i := 0; i < 22; i++ {
|
|
srs = append(srs, generated.VerencShare{
|
|
S1: data[6628+(i*(56+56+8)) : 6684+(i*(56+56+8))],
|
|
S2: data[6684+(i*(56+56+8)) : 6740+(i*(56+56+8))],
|
|
I: binary.BigEndian.Uint64(data[6740+(i*(56+56+8)) : 6748+(i*(56+56+8))]),
|
|
})
|
|
}
|
|
|
|
return MPCitHVerEncProof{
|
|
generated.VerencProofAndBlindingKey{
|
|
BlindingPubkey: data[:57],
|
|
EncryptionKey: data[57:114],
|
|
Statement: data[114:171],
|
|
Challenge: data[171:235],
|
|
Polycom: polycom,
|
|
Ctexts: ctexts,
|
|
SharesRands: srs,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) ToBytes() []byte {
|
|
output := []byte{}
|
|
output = append(output, p.BlindingPubkey...)
|
|
output = append(output, p.EncryptionKey...)
|
|
output = append(output, p.Statement...)
|
|
output = append(output, p.Challenge...)
|
|
|
|
for _, pol := range p.Polycom {
|
|
output = append(output, pol...)
|
|
}
|
|
|
|
for _, ct := range p.Ctexts {
|
|
output = append(output, ct.C1...)
|
|
output = append(output, ct.C2...)
|
|
output = binary.BigEndian.AppendUint64(output, ct.I)
|
|
}
|
|
|
|
for _, sr := range p.SharesRands {
|
|
output = append(output, sr.S1...)
|
|
output = append(output, sr.S2...)
|
|
output = binary.BigEndian.AppendUint64(output, sr.I)
|
|
}
|
|
|
|
return output
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) VerifyStatement(input []byte) bool {
|
|
return VerencVerifyStatement(input, p.BlindingPubkey, p.Statement)
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) GetStatement() []byte {
|
|
return slices.Clone(p.Statement)
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) GetEncryptionKey() []byte {
|
|
return slices.Clone(p.EncryptionKey)
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) Compress() crypto.VerEnc {
|
|
compressed := VerencCompress(generated.VerencProof{
|
|
BlindingPubkey: p.BlindingPubkey,
|
|
EncryptionKey: p.EncryptionKey,
|
|
Statement: p.Statement,
|
|
Challenge: p.Challenge,
|
|
Polycom: p.Polycom,
|
|
Ctexts: p.Ctexts,
|
|
SharesRands: p.SharesRands,
|
|
})
|
|
return MPCitHVerEnc{
|
|
CompressedCiphertext: compressed,
|
|
BlindingPubkey: p.BlindingPubkey,
|
|
Statement: p.Statement,
|
|
}
|
|
}
|
|
|
|
func (p MPCitHVerEncProof) Verify() bool {
|
|
return VerencVerify(generated.VerencProof{
|
|
BlindingPubkey: p.BlindingPubkey,
|
|
EncryptionKey: p.EncryptionKey,
|
|
Statement: p.Statement,
|
|
Challenge: p.Challenge,
|
|
Polycom: p.Polycom,
|
|
Ctexts: p.Ctexts,
|
|
SharesRands: p.SharesRands,
|
|
})
|
|
}
|
|
|
|
type InlineEnc struct {
|
|
iv []byte
|
|
ciphertext []byte
|
|
}
|
|
|
|
func MPCitHVerEncFromBytes(data []byte) crypto.VerEnc {
|
|
if len(data) < 621 {
|
|
return MPCitHVerEnc{}
|
|
}
|
|
|
|
ciphertext := generated.CompressedCiphertext{}
|
|
for i := 0; i < 3; i++ {
|
|
ciphertext.Ctexts = append(ciphertext.Ctexts, generated.VerencCiphertext{
|
|
C1: data[0+(i*(57+56)) : 57+(i*(57+56))],
|
|
C2: data[57+(i*(57+56)) : 113+(i*(57+56))],
|
|
})
|
|
ciphertext.Aux = append(ciphertext.Aux, data[339+(i*56):395+(i*56)])
|
|
}
|
|
return MPCitHVerEnc{
|
|
CompressedCiphertext: ciphertext,
|
|
BlindingPubkey: data[507:564],
|
|
Statement: data[564:621],
|
|
}
|
|
}
|
|
|
|
func (e MPCitHVerEnc) ToBytes() []byte {
|
|
output := []byte{}
|
|
for _, ct := range e.Ctexts {
|
|
output = append(output, ct.C1...)
|
|
output = append(output, ct.C2...)
|
|
}
|
|
for _, a := range e.Aux {
|
|
output = append(output, a...)
|
|
}
|
|
output = append(output, e.BlindingPubkey...)
|
|
output = append(output, e.Statement...)
|
|
return output
|
|
}
|
|
|
|
func (e MPCitHVerEnc) GetStatement() []byte {
|
|
return e.Statement
|
|
}
|
|
|
|
func (e MPCitHVerEnc) Verify(proof []byte) bool {
|
|
proofData := MPCitHVerEncProofFromBytes(proof)
|
|
return proofData.Verify()
|
|
}
|
|
|
|
type MPCitHVerifiableEncryptor struct {
|
|
parallelism int
|
|
lruCache *lru.Cache[string, crypto.VerEnc]
|
|
}
|
|
|
|
func NewMPCitHVerifiableEncryptor(parallelism int) *MPCitHVerifiableEncryptor {
|
|
cache, err := lru.New[string, crypto.VerEnc](10000)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return &MPCitHVerifiableEncryptor{
|
|
parallelism: parallelism,
|
|
lruCache: cache,
|
|
}
|
|
}
|
|
|
|
func (v *MPCitHVerifiableEncryptor) ProofFromBytes(
|
|
data []byte,
|
|
) crypto.VerEncProof {
|
|
return MPCitHVerEncProofFromBytes(data)
|
|
}
|
|
|
|
func (v *MPCitHVerifiableEncryptor) FromBytes(data []byte) crypto.VerEnc {
|
|
return MPCitHVerEncFromBytes(data)
|
|
}
|
|
|
|
func (v *MPCitHVerifiableEncryptor) Encrypt(
|
|
data []byte,
|
|
publicKey []byte,
|
|
) []crypto.VerEncProof {
|
|
chunks := ChunkDataForVerenc(data)
|
|
results := make([]crypto.VerEncProof, len(chunks))
|
|
var wg sync.WaitGroup
|
|
throttle := make(chan struct{}, v.parallelism)
|
|
for i, chunk := range chunks {
|
|
throttle <- struct{}{}
|
|
wg.Add(1)
|
|
go func(chunk []byte, i int) {
|
|
defer func() { <-throttle }()
|
|
defer wg.Done()
|
|
proof := NewVerencProofEncryptOnly(chunk, publicKey)
|
|
results[i] = MPCitHVerEncProof{
|
|
generated.VerencProofAndBlindingKey{
|
|
BlindingKey: proof.BlindingKey,
|
|
BlindingPubkey: proof.BlindingPubkey,
|
|
EncryptionKey: proof.EncryptionKey,
|
|
Statement: proof.Statement,
|
|
Challenge: proof.Challenge,
|
|
Polycom: proof.Polycom,
|
|
Ctexts: proof.Ctexts,
|
|
SharesRands: proof.SharesRands,
|
|
},
|
|
}
|
|
}(chunk, i)
|
|
}
|
|
wg.Wait()
|
|
return results
|
|
}
|
|
|
|
func (v *MPCitHVerifiableEncryptor) EncryptAndCompress(
|
|
data []byte,
|
|
publicKey []byte,
|
|
) []crypto.VerEnc {
|
|
chunks := ChunkDataForVerenc(data)
|
|
results := make([]crypto.VerEnc, len(chunks))
|
|
var wg sync.WaitGroup
|
|
throttle := make(chan struct{}, v.parallelism)
|
|
for i, chunk := range chunks {
|
|
throttle <- struct{}{}
|
|
wg.Add(1)
|
|
go func(chunk []byte, i int) {
|
|
defer func() { <-throttle }()
|
|
defer wg.Done()
|
|
existing, ok := v.lruCache.Get(string(publicKey) + string(chunk))
|
|
if ok {
|
|
results[i] = existing
|
|
} else {
|
|
proof := NewVerencProofEncryptOnly(chunk, publicKey)
|
|
result := MPCitHVerEncProof{
|
|
generated.VerencProofAndBlindingKey{
|
|
BlindingKey: proof.BlindingKey,
|
|
BlindingPubkey: proof.BlindingPubkey,
|
|
EncryptionKey: proof.EncryptionKey,
|
|
Statement: proof.Statement,
|
|
Challenge: proof.Challenge,
|
|
Polycom: proof.Polycom,
|
|
Ctexts: proof.Ctexts,
|
|
SharesRands: proof.SharesRands,
|
|
},
|
|
}
|
|
results[i] = result.Compress()
|
|
v.lruCache.Add(string(publicKey)+string(chunk), results[i])
|
|
}
|
|
}(chunk, i)
|
|
}
|
|
wg.Wait()
|
|
return results
|
|
}
|
|
|
|
func (v *MPCitHVerifiableEncryptor) Decrypt(
|
|
encrypted []crypto.VerEnc,
|
|
decyptionKey []byte,
|
|
) []byte {
|
|
results := make([][]byte, len(encrypted))
|
|
var wg sync.WaitGroup
|
|
throttle := make(chan struct{}, v.parallelism)
|
|
for i, chunk := range encrypted {
|
|
throttle <- struct{}{}
|
|
wg.Add(1)
|
|
go func(chunk crypto.VerEnc, i int) {
|
|
defer func() { <-throttle }()
|
|
defer wg.Done()
|
|
results[i] = VerencRecover(generated.VerencDecrypt{
|
|
BlindingPubkey: chunk.(MPCitHVerEnc).BlindingPubkey,
|
|
DecryptionKey: decyptionKey,
|
|
Statement: chunk.(MPCitHVerEnc).Statement,
|
|
Ciphertexts: chunk.(MPCitHVerEnc).CompressedCiphertext,
|
|
})
|
|
}(chunk, i)
|
|
}
|
|
wg.Wait()
|
|
return CombineChunkedData(results)
|
|
}
|