init: v1.0.0
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
package elgamal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"xdx.jelly/xgcl/grand"
|
||||
)
|
||||
|
||||
var Reader = grand.Reader
|
||||
|
||||
type Params struct {
|
||||
isMont bool // Is Montgomery represent
|
||||
p *big.Int
|
||||
q *big.Int
|
||||
g *big.Int
|
||||
pMont *big.Int
|
||||
qMont *big.Int
|
||||
gMont *big.Int
|
||||
}
|
||||
|
||||
func (p *Params) P() *big.Int {
|
||||
return p.p
|
||||
}
|
||||
func (p *Params) Q() *big.Int {
|
||||
return p.q
|
||||
}
|
||||
func (p *Params) G() *big.Int {
|
||||
return p.g
|
||||
}
|
||||
|
||||
type PublicKey struct {
|
||||
y big.Int
|
||||
Params *Params
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
x big.Int
|
||||
PublicKey
|
||||
}
|
||||
type Cipher struct {
|
||||
u big.Int
|
||||
v big.Int
|
||||
}
|
||||
|
||||
func GenerateKey(rnd io.Reader, params *Params) (*PrivateKey, *PublicKey, error) {
|
||||
x, err := rand.Int(rnd, params.q)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
y := new(big.Int).Exp(params.g, x, params.p)
|
||||
sk := &PrivateKey{
|
||||
x: *x,
|
||||
PublicKey: PublicKey{
|
||||
y: *y,
|
||||
Params: P1024,
|
||||
},
|
||||
}
|
||||
pk := &sk.PublicKey
|
||||
return sk, pk, nil
|
||||
}
|
||||
|
||||
// m = g^M mod p for some M
|
||||
// rnd can be nil, io.Reader or []byte
|
||||
func (pk *PublicKey) Encryption(m *big.Int, rnd any) (*Cipher, error) {
|
||||
var r *big.Int
|
||||
var err error
|
||||
p := pk.Params.p
|
||||
q := pk.Params.q
|
||||
g := pk.Params.g
|
||||
|
||||
switch rnd := rnd.(type) {
|
||||
case nil:
|
||||
rnd = Reader
|
||||
case io.Reader:
|
||||
r, err = rand.Int(rnd, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case []byte:
|
||||
r = new(big.Int).SetBytes(rnd)
|
||||
if r.Cmp(q) >= 0 {
|
||||
return nil, errors.New("random bytes too large")
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("rnd must be io.Reader or []bytes")
|
||||
}
|
||||
|
||||
c := &Cipher{}
|
||||
c.u.Exp(g, r, p)
|
||||
c.v.Exp(&pk.y, r, p)
|
||||
c.v.Mul(&c.v, m)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (sk *PrivateKey) Decryption(c *Cipher) (*big.Int, error) {
|
||||
p := sk.PublicKey.Params.p
|
||||
u := &c.u
|
||||
v := &c.v
|
||||
z := new(big.Int)
|
||||
z.Exp(u, &sk.x, p)
|
||||
z.ModInverse(z, p)
|
||||
z.Mul(z, v)
|
||||
z.Mod(z, p)
|
||||
return z, nil
|
||||
}
|
||||
|
||||
func (c *Cipher) HomoMap(c1 *Cipher, c2 *Cipher) (*Cipher, error) {
|
||||
c.u.Mul(&c1.u, &c2.u)
|
||||
c.v.Mul(&c1.v, &c2.v)
|
||||
return c, nil
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package elgamal
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"xdx.jelly/xgcl/grand"
|
||||
)
|
||||
|
||||
func TestElGamal(t *testing.T) {
|
||||
x := bigFromBase16("013d5955a5e91b8fed1b56b6bdcd467939de9bfc")
|
||||
y := bigFromBase16("b7866990d044b1bccbbcf84c29f145ee17d4f4608c79a55e249e9e108b91e36381944fa3c0c3f51876f63bce7bb30ffde9ca02265e916dd3fb2e060b0dfeaaa67d5a359159b948c3df1141f0e0a22380a3633c1ffbcb1c228ffe4ef0bab52293bfdff4b64e3f362d63b11a4d2507f6e9e98de71aff09fdb64e3737c046044138")
|
||||
// M := bigFromBase16("4142434445464748494a31323334353637383930")
|
||||
// m := new(big.Int).Exp(P1024.g, M, P1024.p)
|
||||
m, _ := rand.Int(grand.Reader, P1024.p)
|
||||
sk := &PrivateKey{
|
||||
x: *x,
|
||||
PublicKey: PublicKey{
|
||||
y: *y,
|
||||
Params: P1024,
|
||||
},
|
||||
}
|
||||
pk := &sk.PublicKey
|
||||
b, _ := hex.DecodeString("d8d0f2d6a3e2d745ab4410e2042a740e7a81a280")
|
||||
c1, err := pk.Encryption(m, b)
|
||||
assert.Nil(t, err)
|
||||
c2, err := pk.Encryption(m, grand.Reader)
|
||||
c, _ := new(Cipher).HomoMap(c1, c2)
|
||||
mm0, _ := sk.Decryption(c)
|
||||
mm1 := new(big.Int).Mul(m, m)
|
||||
mm1.Mod(mm1, pk.Params.p)
|
||||
|
||||
assert.Zero(t, mm0.Cmp(mm1))
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package elgamal
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
func bigFromBase16(s string) *big.Int {
|
||||
b, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return new(big.Int).SetBytes(b)
|
||||
}
|
||||
|
||||
var P1024 = &Params{
|
||||
p: bigFromBase16("e5256a788f875183ec56a332d38db31de883cded25ae635a656823b5c801b44a104f4e1d604153adaaa5d6d107feb3a8e721a32f3e6780645c85de2d4f4f85568767efc9b8363193497c052a5b832464b81a209d393eb6d3a464cba0b7607dc79b3611dcd1544e4ed329cc913f68234b1d5f209ae7081c0d44662ee1f86c458f"),
|
||||
q: bigFromBase16("e6fa5be8dfd1a200fd699a9ff4b02761f05fca69"),
|
||||
g: bigFromBase16("5a0c1ebde9c0787f3d426e2036455fcd25bc32b1e666b2ba90dad169af7043c18b266d530d0f607ea46c182dd7c88d919158343441e001b10e36c8ffa03cb80dadcf7e84393561d2f4f2d067222d5a33157b81f4f4a46c9526375920cac73c23e100e8b43eb8a4bc83047ae45b079bca6dbf69b4b0c1e6bffdfd232b99c5d61a"),
|
||||
}
|
||||
Reference in New Issue
Block a user