mirror of
https://github.com/saymrwulf/swisspost-evoting-go-poc.git
synced 2026-09-05 20:30:43 +00:00
50 lines
1.4 KiB
Go
50 lines
1.4 KiB
Go
|
|
package elgamal
|
||
|
|
|
||
|
|
import (
|
||
|
|
emath "github.com/user/evote/pkg/math"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Decrypt computes the ElGamal decryption of a ciphertext.
|
||
|
|
// m_i = phi_i / gamma^sk_i = phi_i * gamma^(-sk_i)
|
||
|
|
func Decrypt(ct Ciphertext, sk PrivateKey) Message {
|
||
|
|
if ct.Size() != sk.Size() {
|
||
|
|
panic("ciphertext size must match secret key size")
|
||
|
|
}
|
||
|
|
|
||
|
|
elems := make([]emath.GqElement, ct.Size())
|
||
|
|
for i := 0; i < ct.Size(); i++ {
|
||
|
|
// gamma^sk_i
|
||
|
|
gammaSk := ct.Gamma.Exponentiate(sk.Get(i))
|
||
|
|
// m_i = phi_i / gamma^sk_i
|
||
|
|
elems[i] = ct.GetPhi(i).Divide(gammaSk)
|
||
|
|
}
|
||
|
|
|
||
|
|
return Message{Elements: emath.GqVectorOf(elems...)}
|
||
|
|
}
|
||
|
|
|
||
|
|
// PartialDecrypt computes partial decryption using one key share.
|
||
|
|
// For each phi: phi_i' = phi_i / gamma^sk_i
|
||
|
|
// The gamma is left unchanged for further partial decryptions.
|
||
|
|
func PartialDecrypt(ct Ciphertext, sk PrivateKey) Ciphertext {
|
||
|
|
if ct.Size() != sk.Size() {
|
||
|
|
panic("ciphertext size must match secret key size")
|
||
|
|
}
|
||
|
|
|
||
|
|
phis := make([]emath.GqElement, ct.Size())
|
||
|
|
for i := 0; i < ct.Size(); i++ {
|
||
|
|
gammaSk := ct.Gamma.Exponentiate(sk.Get(i))
|
||
|
|
phis[i] = ct.GetPhi(i).Divide(gammaSk)
|
||
|
|
}
|
||
|
|
|
||
|
|
return Ciphertext{
|
||
|
|
Gamma: ct.Gamma,
|
||
|
|
Phis: emath.GqVectorOf(phis...),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExtractMessage extracts the plaintext from a fully decrypted ciphertext.
|
||
|
|
// After all partial decryptions, the phis contain the plaintext directly.
|
||
|
|
func ExtractMessage(ct Ciphertext) Message {
|
||
|
|
return Message{Elements: ct.Phis}
|
||
|
|
}
|