Browse Source

paillier encrypt & decrypt, homomorphic addition

master
arnaucode 5 years ago
parent
commit
6ce09111f9
6 changed files with 200 additions and 25 deletions
  1. +5
    -0
      README.md
  2. +111
    -0
      paillier/paillier.go
  3. +41
    -0
      paillier/paillier_test.go
  4. +5
    -0
      prime/prime.go
  5. +23
    -20
      rsa/rsa.go
  6. +15
    -5
      rsa/rsa_test.go

+ 5
- 0
README.md

@ -14,5 +14,10 @@ Crypto algorithms from scratch. Academic purposes only.
- [x] Homomorphic Multiplication
## Paillier
- [x] GenerateKeyPair
- [x] Encrypt
- [x] Decrypt
- [x] Homomorphic Addition
## ECC
## Shamir Secret Sharing

+ 111
- 0
paillier/paillier.go

@ -0,0 +1,111 @@
package paillier
import (
"crypto/rand"
"errors"
"math/big"
prime "../prime"
)
const (
bits = 16
)
type PublicKey struct {
N *big.Int `json:"n"`
G *big.Int `json:"g"`
}
type PrivateKey struct {
Lambda *big.Int `json:"lambda"`
Mu *big.Int `json:"mu"`
}
type Key struct {
PubK PublicKey
PrivK PrivateKey
}
func GenerateKeyPair() (key Key, err error) {
p, err := rand.Prime(rand.Reader, bits/2)
if err != nil {
return key, err
}
q, err := rand.Prime(rand.Reader, bits/2)
if err != nil {
return key, err
}
pq := new(big.Int).Mul(p, q)
p1q1 := big.NewInt((p.Int64() - 1) * (q.Int64() - 1))
gcd := new(big.Int).GCD(nil, nil, pq, p1q1)
if gcd.Int64() != int64(1) {
return key, errors.New("gcd comprovation failed")
}
n := new(big.Int).Mul(p, q)
lambda := big.NewInt(int64(Lcm(float64(p.Int64())-1, float64(q.Int64())-1)))
//g generation
alpha := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
beta := big.NewInt(int64(prime.RandInt(0, int(n.Int64()))))
alphan := new(big.Int).Mul(alpha, n)
alphan1 := new(big.Int).Add(alphan, big.NewInt(1))
betaN := new(big.Int).Exp(beta, n, nil)
ab := new(big.Int).Mul(alphan1, betaN)
n2 := new(big.Int).Mul(n, n)
g := new(big.Int).Mod(ab, n2)
//in some Paillier implementations use this:
// g = new(big.Int).Add(n, big.NewInt(1))
key.PubK.N = n
key.PubK.G = g
//mu generation
Glambda := new(big.Int).Exp(g, lambda, nil)
u := new(big.Int).Mod(Glambda, n2)
L := L(u, n)
mu := new(big.Int).ModInverse(L, n)
key.PrivK.Lambda = lambda
key.PrivK.Mu = mu
return key, nil
}
func Lcm(a, b float64) float64 {
r := (a * b) / float64(prime.Gcd(int(a), int(b)))
return r
}
func L(u *big.Int, n *big.Int) *big.Int {
u1 := new(big.Int).Sub(u, big.NewInt(1))
L := new(big.Int).Div(u1, n)
return L
}
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
gM := new(big.Int).Exp(pubK.G, m, nil)
r := big.NewInt(int64(prime.RandInt(0, int(pubK.N.Int64()))))
rN := new(big.Int).Exp(r, pubK.N, nil)
gMrN := new(big.Int).Mul(gM, rN)
n2 := new(big.Int).Mul(pubK.N, pubK.N)
c := new(big.Int).Mod(gMrN, n2)
return c
}
func Decrypt(c *big.Int, pubK PublicKey, privK PrivateKey) *big.Int {
cLambda := new(big.Int).Exp(c, privK.Lambda, nil)
n2 := new(big.Int).Mul(pubK.N, pubK.N)
u := new(big.Int).Mod(cLambda, n2)
L := L(u, pubK.N)
LMu := new(big.Int).Mul(L, privK.Mu)
m := new(big.Int).Mod(LMu, pubK.N)
return m
}
func HomomorphicAddition(c1 *big.Int, c2 *big.Int, pubK PublicKey) *big.Int {
c1c2 := new(big.Int).Mul(c1, c2)
n2 := new(big.Int).Mul(pubK.N, pubK.N)
d := new(big.Int).Mod(c1c2, n2)
return d
}

+ 41
- 0
paillier/paillier_test.go

@ -0,0 +1,41 @@
package paillier
import (
"bytes"
"fmt"
"math/big"
"testing"
)
func TestEncryptDecrypt(t *testing.T) {
key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
fmt.Println(key)
mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)
c := Encrypt(m, key.PubK)
d := Decrypt(c, key.PubK, key.PrivK)
if m == d {
fmt.Println(key)
t.Errorf("m not equal to decrypted")
}
}
func TestHomomorphicAddition(t *testing.T) {
key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
n1 := big.NewInt(int64(110))
n2 := big.NewInt(int64(150))
c1 := Encrypt(n1, key.PubK)
c2 := Encrypt(n2, key.PubK)
c3c4 := HomomorphicAddition(c1, c2, key.PubK)
d := Decrypt(c3c4, key.PubK, key.PrivK)
if !bytes.Equal(new(big.Int).Add(n1, n2).Bytes(), d.Bytes()) {
fmt.Println(key)
t.Errorf("decrypted result not equal to original result")
}
}

+ 5
- 0
prime/prime.go

@ -2,6 +2,11 @@ package prime
import "math/rand"
const (
MaxPrime = 2000
MinPrime = 500
)
func RandInt(min int, max int) int {
r := rand.Intn(max-min) + min
return r

+ 23
- 20
rsa/rsa.go

@ -2,18 +2,16 @@ package rsa
import (
"bytes"
"crypto/rand"
"math/big"
"math/rand"
"time"
prime "../prime"
)
const (
MaxPrime = 2000
MinPrime = 500
bits = 512 // 2048
)
var bigOne = big.NewInt(int64(1))
type PublicKey struct {
E *big.Int `json:"e"`
N *big.Int `json:"n"`
@ -32,37 +30,42 @@ type Key struct {
PrivK PrivateKey
}
func GenerateKeyPair() (key Key) {
rand.Seed(time.Now().Unix())
p := prime.RandPrime(MinPrime, MaxPrime)
q := prime.RandPrime(MinPrime, MaxPrime)
func GenerateKeyPair() (key Key, err error) {
p, err := rand.Prime(rand.Reader, bits/2)
if err != nil {
return key, err
}
q, err := rand.Prime(rand.Reader, bits/2)
if err != nil {
return key, err
}
n := p * q
phi := (p - 1) * (q - 1)
n := new(big.Int).Mul(p, q)
p_1 := new(big.Int).Sub(p, bigOne)
q_1 := new(big.Int).Sub(q, bigOne)
phi := new(big.Int).Mul(p_1, q_1)
e := 65537
var pubK PublicKey
pubK.E = big.NewInt(int64(e))
pubK.N = big.NewInt(int64(n))
pubK.N = n
d := new(big.Int).ModInverse(big.NewInt(int64(e)), big.NewInt(int64(phi)))
d := new(big.Int).ModInverse(big.NewInt(int64(e)), phi)
var privK PrivateKey
privK.D = d
privK.N = big.NewInt(int64(n))
privK.N = n
key.PubK = pubK
key.PrivK = privK
return key
return key, nil
}
func Encrypt(m *big.Int, pubK PublicKey) *big.Int {
Me := new(big.Int).Exp(m, pubK.E, nil)
c := new(big.Int).Mod(Me, pubK.N)
c := new(big.Int).Exp(m, pubK.E, pubK.N)
return c
}
func Decrypt(c *big.Int, privK PrivateKey) *big.Int {
Cd := new(big.Int).Exp(c, privK.D, nil)
m := new(big.Int).Mod(Cd, privK.N)
m := new(big.Int).Exp(c, privK.D, privK.N)
return m
}

+ 15
- 5
rsa/rsa_test.go

@ -2,13 +2,17 @@ package rsa
import (
"bytes"
"fmt"
"math/big"
"testing"
)
func TestEncryptDecrypt(t *testing.T) {
key := GenerateKeyPair()
key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
fmt.Println(key)
mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)
c := Encrypt(m, key.PubK)
@ -19,7 +23,10 @@ func TestEncryptDecrypt(t *testing.T) {
}
}
func TestBlindSignature(t *testing.T) {
key := GenerateKeyPair()
key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
mBytes := []byte("Hi")
m := new(big.Int).SetBytes(mBytes)
@ -39,8 +46,11 @@ func TestBlindSignature(t *testing.T) {
}
}
func TestHomomorphiMultiplication(t *testing.T) {
key := GenerateKeyPair()
func TestHomomorphicMultiplication(t *testing.T) {
key, err := GenerateKeyPair()
if err != nil {
t.Errorf(err.Error())
}
n1 := big.NewInt(int64(11))
n2 := big.NewInt(int64(15))

Loading…
Cancel
Save